Merge pull request #13468 from hashicorp/f-oracle-compute

provider/opc: Add Oracle Compute Provider
This commit is contained in:
Jake Champlin 2017-04-20 14:52:39 -04:00 committed by GitHub
commit 35388cbc31
145 changed files with 16378 additions and 0 deletions

View File

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

View File

@ -0,0 +1,60 @@
package opc
import (
"fmt"
"log"
"net/url"
"strings"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/go-oracle-terraform/opc"
"github.com/hashicorp/terraform/helper/logging"
)
type Config struct {
User string
Password string
IdentityDomain string
Endpoint string
MaxRetryTimeout int
}
type OPCClient struct {
Client *compute.Client
MaxRetryTimeout int
}
func (c *Config) Client() (*compute.Client, error) {
u, err := url.ParseRequestURI(c.Endpoint)
if err != nil {
return nil, fmt.Errorf("Invalid endpoint URI: %s", err)
}
config := opc.Config{
IdentityDomain: &c.IdentityDomain,
Username: &c.User,
Password: &c.Password,
APIEndpoint: u,
HTTPClient: cleanhttp.DefaultClient(),
}
if logging.IsDebugOrHigher() {
config.LogLevel = opc.LogDebug
config.Logger = opcLogger{}
}
return compute.NewComputeClient(&config)
}
type opcLogger struct{}
func (l opcLogger) Log(args ...interface{}) {
tokens := make([]string, 0, len(args))
for _, arg := range args {
if token, ok := arg.(string); ok {
tokens = append(tokens, token)
}
}
log.Printf("[DEBUG] [go-oracle-terraform]: %s", strings.Join(tokens, " "))
}

View File

@ -0,0 +1,176 @@
package opc
import (
"fmt"
"log"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceNetworkInterface() *schema.Resource {
return &schema.Resource{
Read: dataSourceNetworkInterfaceRead,
Schema: map[string]*schema.Schema{
"instance_id": {
Type: schema.TypeString,
Required: true,
},
"instance_name": {
Type: schema.TypeString,
Required: true,
},
"interface": {
Type: schema.TypeString,
Required: true,
},
// Computed Values returned from the data source lookup
"dns": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
},
"ip_network": {
Type: schema.TypeString,
Computed: true,
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
"model": {
Type: schema.TypeString,
Computed: true,
},
"name_servers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"nat": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"search_domains": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"sec_lists": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"shared_network": {
Type: schema.TypeBool,
Computed: true,
},
"vnic": {
Type: schema.TypeString,
Computed: true,
},
"vnic_sets": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}
func dataSourceNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Instances()
// Get required attributes
instance_name := d.Get("instance_name").(string)
instance_id := d.Get("instance_id").(string)
targetInterface := d.Get("interface").(string)
// Get instance
input := &compute.GetInstanceInput{
Name: instance_name,
ID: instance_id,
}
instance, err := client.GetInstance(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading instance %q: %v", instance_name, err)
}
result := compute.NetworkingInfo{}
// If the target instance has no network interfaces, return
if instance.Networking == nil {
d.SetId("")
return nil
}
// Set the computed fields
result = instance.Networking[targetInterface]
// Check if the target interface exists or not
if &result == nil {
log.Printf("[WARN] %q networking interface not found on instance %q", targetInterface, instance_name)
}
d.SetId(fmt.Sprintf("%s-%s", instance_name, targetInterface))
// vNIC is a required field for an IP Network interface, and can only be set if the network
// interface is inside an IP Network. Use this key to determine shared_network status
if result.Vnic != "" {
d.Set("shared_network", false)
} else {
d.Set("shared_network", true)
}
d.Set("ip_address", result.IPAddress)
d.Set("ip_network", result.IPNetwork)
d.Set("mac_address", result.MACAddress)
d.Set("model", result.Model)
d.Set("vnic", result.Vnic)
if err := setStringList(d, "dns", result.DNS); err != nil {
return err
}
if err := setStringList(d, "name_servers", result.NameServers); err != nil {
return err
}
if err := setStringList(d, "nat", result.Nat); err != nil {
return err
}
if err := setStringList(d, "search_domains", result.SearchDomains); err != nil {
return err
}
if err := setStringList(d, "sec_lists", result.SecLists); err != nil {
return err
}
if err := setStringList(d, "vnic_sets", result.VnicSets); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,101 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCDataSourceNetworkInterface_basic(t *testing.T) {
rInt := acctest.RandInt()
resName := "data.opc_compute_network_interface.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceNetworkInterfaceBasic(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resName, "ip_network", fmt.Sprintf("testing-ip-network-%d", rInt)),
resource.TestCheckResourceAttr(resName, "vnic", fmt.Sprintf("ip-network-test-%d", rInt)),
resource.TestCheckResourceAttr(resName, "shared_network", "false"),
),
},
},
})
}
func TestAccOPCDataSourceNetworkInterface_sharedNetwork(t *testing.T) {
rInt := acctest.RandInt()
resName := "data.opc_compute_network_interface.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceNetworkInterfaceShared(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resName, "nat.#", "1"),
resource.TestCheckResourceAttr(resName, "shared_network", "true"),
resource.TestCheckResourceAttr(resName, "sec_lists.#", "1"),
resource.TestCheckResourceAttr(resName, "name_servers.#", "0"),
resource.TestCheckResourceAttr(resName, "vnic_sets.#", "0"),
),
},
},
})
}
func testAccDataSourceNetworkInterfaceBasic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-ip-network-%d"
description = "testing-ip-network-instance"
ip_address_prefix = "10.1.12.0/24"
}
resource "opc_compute_instance" "test" {
name = "test-%d"
label = "test"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "ip-network-test-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "test" {
instance_name = "${opc_compute_instance.test.name}"
instance_id = "${opc_compute_instance.test.id}"
interface = "eth0"
}`, rInt, rInt, rInt)
}
func testAccDataSourceNetworkInterfaceShared(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_instance" "test" {
name = "test-%d"
label = "test"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
tags = ["tag1", "tag2"]
networking_info {
index = 0
nat = ["ippool:/oracle/public/ippool"]
shared_network = true
}
}
data "opc_compute_network_interface" "test" {
instance_name = "${opc_compute_instance.test.name}"
instance_id = "${opc_compute_instance.test.id}"
interface = "eth0"
}`, rInt)
}

View File

@ -0,0 +1,72 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceVNIC() *schema.Resource {
return &schema.Resource{
Read: dataSourceVNICRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsComputedSchema(),
"transit_flag": {
Type: schema.TypeBool,
Computed: true,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func dataSourceVNICRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).VirtNICs()
name := d.Get("name").(string)
input := &compute.GetVirtualNICInput{
Name: name,
}
vnic, err := client.GetVirtualNIC(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading vnic %s: %s", name, err)
}
d.SetId(name)
d.Set("description", vnic.Description)
d.Set("mac_address", vnic.MACAddress)
d.Set("transit_flag", vnic.TransitFlag)
d.Set("uri", vnic.Uri)
if err := setStringList(d, "tags", vnic.Tags); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,62 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCVNIC_Basic(t *testing.T) {
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccVnicBasic(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"data.opc_compute_vnic.foo", "mac_address", "02:5a:cd:ec:2e:4c"),
resource.TestCheckResourceAttr(
"data.opc_compute_vnic.foo", "transit_flag", "false"),
),
},
},
})
}
func testAccVnicBasic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-vnic-data-%d"
description = "testing-vnic-data"
ip_address_prefix = "10.1.13.0/24"
}
resource "opc_compute_instance" "test" {
name = "test-%d"
label = "test"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-data-%d"
shared_network = false
mac_address = "02:5a:cd:ec:2e:4c"
}
}
data "opc_compute_network_interface" "eth0" {
instance_name = "${opc_compute_instance.test.name}"
instance_id = "${opc_compute_instance.test.id}"
interface = "eth0"
}
data "opc_compute_vnic" "foo" {
name = "${data.opc_compute_network_interface.eth0.vnic}"
}`, rInt, rInt, rInt)
}

View File

@ -0,0 +1,47 @@
package opc
import (
"sort"
"github.com/hashicorp/terraform/helper/schema"
)
// Helper function to get a string list from the schema, and alpha-sort it
func getStringList(d *schema.ResourceData, key string) []string {
if _, ok := d.GetOk(key); !ok {
return nil
}
l := d.Get(key).([]interface{})
res := make([]string, len(l))
for i, v := range l {
res[i] = v.(string)
}
sort.Strings(res)
return res
}
// Helper function to set a string list in the schema, in an alpha-sorted order.
func setStringList(d *schema.ResourceData, key string, value []string) error {
sort.Strings(value)
return d.Set(key, value)
}
// Helper function to get an int list from the schema, and numerically sort it
func getIntList(d *schema.ResourceData, key string) []int {
if _, ok := d.GetOk(key); !ok {
return nil
}
l := d.Get(key).([]interface{})
res := make([]int, len(l))
for i, v := range l {
res[i] = v.(int)
}
sort.Ints(res)
return res
}
func setIntList(d *schema.ResourceData, key string, value []int) error {
sort.Ints(value)
return d.Set(key, value)
}

View File

@ -0,0 +1,58 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCACL_importBasic(t *testing.T) {
resourceName := "opc_compute_acl.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccACLBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckACLDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCACL_importDisabled(t *testing.T) {
resourceName := "opc_compute_acl.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccACLDisabled, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckACLDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,57 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCImageList_importBasic(t *testing.T) {
resourceName := "opc_compute_image_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageList_basic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCImageList_importComplete(t *testing.T) {
resourceName := "opc_compute_image_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageList_complete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,36 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCInstance_importBasic(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "opc_compute_instance.test"
instanceName := fmt.Sprintf("acc-test-instance-%d", rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceBasic(rInt),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: instanceName + "/",
ImportStateVerifyIgnore: []string{"instance_attributes"},
},
},
})
}

View File

@ -0,0 +1,29 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPAddressAssociation_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_address_association.test"
ri := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPAddressAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccIPAddressAssociationBasic(ri),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,33 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPAddressPrefixSet_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_address_prefix_set.test"
ri := acctest.RandInt()
config := testAccIPAddressPrefixSetBasic(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckIPAddressPrefixSetDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,57 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPAddressReservation_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_address_reservation.test"
ri := acctest.RandInt()
config := testAccOPCIPAddressReservationConfig_Basic(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckIPAddressReservationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCIPAddressReservation_importDisabled(t *testing.T) {
resourceName := "opc_compute_ip_address_reservation.test"
ri := acctest.RandInt()
config := testAccOPCIPAddressReservationConfig_Basic(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckIPAddressReservationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,34 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPAssociation_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_association.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPAssociationBasic, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckIPAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,34 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPNetworkExchange_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_network_exchange.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPNetworkExchangeBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckIPNetworkExchangeDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,33 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPNetwork_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_network.test"
rInt := acctest.RandInt()
config := testAccOPCIPNetworkConfig_Basic(rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccOPCCheckIPNetworkDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,34 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPReservation_importBasic(t *testing.T) {
resourceName := "opc_compute_ip_reservation.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPReservationBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckIPReservationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,33 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCRoute_importBasic(t *testing.T) {
resourceName := "opc_compute_route.test"
ri := acctest.RandInt()
config := testAccOPCRouteConfig_Basic(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckRouteDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,59 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecRule_importBasic(t *testing.T) {
resourceName := "opc_compute_sec_rule.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecRuleBasic, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecRule_importComplete(t *testing.T) {
resourceName := "opc_compute_sec_rule.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecRuleComplete, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,59 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityApplication_importICMP(t *testing.T) {
resourceName := "opc_compute_security_application.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityApplicationICMP, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityApplicationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecurityApplication_importTCP(t *testing.T) {
resourceName := "opc_compute_security_application.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityApplicationTCP, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityApplicationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,59 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityAssociation_importBasic(t *testing.T) {
resourceName := "opc_compute_security_association.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccSecurityAssociationBasic, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecurityAssociation_importComplete(t *testing.T) {
resourceName := "opc_compute_security_association.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccSecurityAssociationComplete, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,34 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityIPList_importBasic(t *testing.T) {
resourceName := "opc_compute_security_ip_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityIPListBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityIPListDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,59 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityList_importBasic(t *testing.T) {
resourceName := "opc_compute_security_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityListBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityListDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecurityList_importComplete(t *testing.T) {
resourceName := "opc_compute_security_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityListComplete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityListDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,58 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityProtocol_importBasic(t *testing.T) {
resourceName := "opc_compute_security_protocol.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityProtocolBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityProtocolDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecurityProtocol_importComplete(t *testing.T) {
resourceName := "opc_compute_security_protocol.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityProtocolComplete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityProtocolDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,58 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSecurityRule_importBasic(t *testing.T) {
resourceName := "opc_compute_security_rule.test"
ri := acctest.RandInt()
config := testAccOPCSecurityRuleConfig_Basic(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSecurityRule_importFull(t *testing.T) {
resourceName := "opc_compute_security_rule.test"
ri := acctest.RandInt()
config := testAccOPCSecurityRuleConfig_Full(ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,59 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCSSHKey_importBasic(t *testing.T) {
resourceName := "opc_compute_ssh_key.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSSHKeyBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSSHKeyDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCSSHKey_importDisabled(t *testing.T) {
resourceName := "opc_compute_ssh_key.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSSHKeyDisabled, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSSHKeyDestroy,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,29 @@
package opc
import (
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCStorageVolumeSnapshot_importBasic(t *testing.T) {
resourceName := "opc_compute_storage_volume_snapshot.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeSnapshotDestroyed),
Steps: []resource.TestStep{
{
Config: testAccStorageVolumeSnapshot_basic(rInt),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,163 @@
package opc
import (
"testing"
"fmt"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCStorageVolume_importBasic(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBasic, rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importComplete(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeComplete, rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importMaxSize(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBasicMaxSize, rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importBootable(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBootable, rInt, rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importImageListEntry(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeImageListEntry, rInt, rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importLowLatency(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := testAccStorageVolumeLowLatency(rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccOPCStorageVolume_importFromSnapshot(t *testing.T) {
resourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
config := testAccStorageVolumeFromSnapshot(rInt)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -0,0 +1,93 @@
package opc
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"user": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("OPC_USERNAME", nil),
Description: "The user name for OPC API operations.",
},
"password": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("OPC_PASSWORD", nil),
Description: "The user password for OPC API operations.",
},
"identity_domain": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("OPC_IDENTITY_DOMAIN", nil),
Description: "The OPC identity domain for API operations",
},
"endpoint": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("OPC_ENDPOINT", nil),
Description: "The HTTP endpoint for OPC API operations.",
},
// TODO Actually implement this
"max_retry_timeout": {
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)",
},
},
DataSourcesMap: map[string]*schema.Resource{
"opc_compute_network_interface": dataSourceNetworkInterface(),
"opc_compute_vnic": dataSourceVNIC(),
},
ResourcesMap: map[string]*schema.Resource{
"opc_compute_ip_network": resourceOPCIPNetwork(),
"opc_compute_acl": resourceOPCACL(),
"opc_compute_image_list": resourceOPCImageList(),
"opc_compute_image_list_entry": resourceOPCImageListEntry(),
"opc_compute_instance": resourceInstance(),
"opc_compute_ip_address_reservation": resourceOPCIPAddressReservation(),
"opc_compute_ip_association": resourceOPCIPAssociation(),
"opc_compute_ip_network_exchange": resourceOPCIPNetworkExchange(),
"opc_compute_ip_reservation": resourceOPCIPReservation(),
"opc_compute_route": resourceOPCRoute(),
"opc_compute_security_application": resourceOPCSecurityApplication(),
"opc_compute_security_association": resourceOPCSecurityAssociation(),
"opc_compute_security_ip_list": resourceOPCSecurityIPList(),
"opc_compute_security_list": resourceOPCSecurityList(),
"opc_compute_security_rule": resourceOPCSecurityRule(),
"opc_compute_sec_rule": resourceOPCSecRule(),
"opc_compute_ssh_key": resourceOPCSSHKey(),
"opc_compute_storage_volume": resourceOPCStorageVolume(),
"opc_compute_storage_volume_snapshot": resourceOPCStorageVolumeSnapshot(),
"opc_compute_vnic_set": resourceOPCVNICSet(),
"opc_compute_security_protocol": resourceOPCSecurityProtocol(),
"opc_compute_ip_address_prefix_set": resourceOPCIPAddressPrefixSet(),
"opc_compute_ip_address_association": resourceOPCIPAddressAssociation(),
},
ConfigureFunc: providerConfigure,
}
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
config := Config{
User: d.Get("user").(string),
Password: d.Get("password").(string),
IdentityDomain: d.Get("identity_domain").(string),
Endpoint: d.Get("endpoint").(string),
MaxRetryTimeout: d.Get("max_retry_timeout").(int),
}
return config.Client()
}

View File

@ -0,0 +1,62 @@
package opc
import (
"fmt"
"os"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"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("Error creating Provider: %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 {
*compute.Client
*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{
Client: testAccProvider.Meta().(*compute.Client),
InstanceState: rs.Primary,
}
return f(state)
}
}

View File

@ -0,0 +1,151 @@
package opc
import (
"fmt"
"log"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCACL() *schema.Resource {
return &schema.Resource{
Create: resourceOPCACLCreate,
Read: resourceOPCACLRead,
Update: resourceOPCACLUpdate,
Delete: resourceOPCACLDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"tags": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
ForceNew: true,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCACLCreate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
log.Print("[DEBUG] Creating acl")
client := meta.(*compute.Client).ACLs()
input := compute.CreateACLInput{
Name: d.Get("name").(string),
Enabled: d.Get("enabled").(bool),
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateACL(&input)
if err != nil {
return fmt.Errorf("Error creating ACL: %s", err)
}
d.SetId(info.Name)
return resourceOPCACLRead(d, meta)
}
func resourceOPCACLRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).ACLs()
log.Printf("[DEBUG] Reading state of ip reservation %s", d.Id())
getInput := compute.GetACLInput{
Name: d.Id(),
}
result, err := client.GetACL(&getInput)
if err != nil {
// ACL does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading acl %s: %s", d.Id(), err)
}
log.Printf("[DEBUG] Read state of acl %s: %#v", d.Id(), result)
d.Set("name", result.Name)
d.Set("enabled", result.Enabled)
d.Set("description", result.Description)
d.Set("uri", result.URI)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCACLUpdate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
log.Print("[DEBUG] Updating acl")
client := meta.(*compute.Client).ACLs()
input := compute.UpdateACLInput{
Name: d.Get("name").(string),
Enabled: d.Get("enabled").(bool),
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateACL(&input)
if err != nil {
return fmt.Errorf("Error updating ACL: %s", err)
}
d.SetId(info.Name)
return resourceOPCACLRead(d, meta)
}
func resourceOPCACLDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).ACLs()
name := d.Id()
log.Printf("[DEBUG] Deleting ACL: %v", name)
input := compute.DeleteACLInput{
Name: name,
}
if err := client.DeleteACL(&input); err != nil {
return fmt.Errorf("Error deleting ACL")
}
return nil
}

View File

@ -0,0 +1,107 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCACL_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccACLBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckACLDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckACLExists,
),
},
},
})
}
func TestAccOPCACL_Update(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccACLBasic, ri)
updatedConfig := fmt.Sprintf(testAccACLDisabled, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckACLDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckACLExists,
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckACLExists,
resource.TestCheckResourceAttr("opc_compute_acl.test", "enabled", "false"),
),
},
},
})
}
func testAccCheckACLExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ACLs()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_acl" {
continue
}
input := compute.GetACLInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetACL(&input); err != nil {
return fmt.Errorf("Error retrieving state of ACL %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckACLDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ACLs()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_acl" {
continue
}
input := compute.GetACLInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetACL(&input); err == nil {
return fmt.Errorf("ACL %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccACLBasic = `
resource "opc_compute_acl" "test" {
name = "test_acl-%d"
description = "test acl"
}
`
var testAccACLDisabled = `
resource "opc_compute_acl" "test" {
name = "test_acl-%d"
description = "test acl"
enabled = false
}
`

View File

@ -0,0 +1,107 @@
package opc
import (
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCImageList() *schema.Resource {
return &schema.Resource{
Create: resourceOPCImageListCreate,
Read: resourceOPCImageListRead,
Update: resourceOPCImageListUpdate,
Delete: resourceOPCImageListDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Required: true,
},
"default": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
},
},
}
}
func resourceOPCImageListCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageList()
name := d.Get("name").(string)
createInput := &compute.CreateImageListInput{
Name: name,
Description: d.Get("description").(string),
Default: d.Get("default").(int),
}
createResult, err := client.CreateImageList(createInput)
if err != nil {
return err
}
d.SetId(createResult.Name)
return resourceOPCImageListRead(d, meta)
}
func resourceOPCImageListUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageList()
name := d.Id()
updateInput := &compute.UpdateImageListInput{
Name: name,
Description: d.Get("description").(string),
Default: d.Get("default").(int),
}
_, err := client.UpdateImageList(updateInput)
if err != nil {
return err
}
return resourceOPCImageListRead(d, meta)
}
func resourceOPCImageListRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageList()
getInput := &compute.GetImageListInput{
Name: d.Id(),
}
getResult, err := client.GetImageList(getInput)
if err != nil {
return err
}
d.Set("name", getResult.Name)
d.Set("description", getResult.Description)
d.Set("default", getResult.Default)
return nil
}
func resourceOPCImageListDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageList()
deleteInput := &compute.DeleteImageListInput{
Name: d.Id(),
}
err := client.DeleteImageList(deleteInput)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,160 @@
package opc
import (
"fmt"
"strconv"
"strings"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/structure"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceOPCImageListEntry() *schema.Resource {
return &schema.Resource{
Create: resourceOPCImageListEntryCreate,
Read: resourceOPCImageListEntryRead,
Delete: resourceOPCImageListEntryDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"machine_images": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"version": {
Type: schema.TypeInt,
ForceNew: true,
Required: true,
},
"attributes": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
ValidateFunc: validation.ValidateJsonString,
DiffSuppressFunc: structure.SuppressJsonDiff,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCImageListEntryCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageListEntries()
name := d.Get("name").(string)
machineImages := expandOPCImageListEntryMachineImages(d)
version := d.Get("version").(int)
createInput := &compute.CreateImageListEntryInput{
Name: name,
MachineImages: machineImages,
Version: version,
}
if v, ok := d.GetOk("attributes"); ok {
attributesString := v.(string)
attributes, err := structure.ExpandJsonFromString(attributesString)
if err != nil {
return err
}
createInput.Attributes = attributes
}
_, err := client.CreateImageListEntry(createInput)
if err != nil {
return err
}
id := generateOPCImageListEntryID(name, version)
d.SetId(id)
return resourceOPCImageListEntryRead(d, meta)
}
func resourceOPCImageListEntryRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageListEntries()
name, version, err := parseOPCImageListEntryID(d.Id())
if err != nil {
return err
}
getInput := compute.GetImageListEntryInput{
Name: *name,
Version: *version,
}
getResult, err := client.GetImageListEntry(&getInput)
if err != nil {
return err
}
attrs, err := structure.FlattenJsonToString(getResult.Attributes)
if err != nil {
return err
}
d.Set("name", name)
d.Set("machine_images", getResult.MachineImages)
d.Set("version", getResult.Version)
d.Set("attributes", attrs)
d.Set("uri", getResult.Uri)
return nil
}
func resourceOPCImageListEntryDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).ImageListEntries()
name, version, err := parseOPCImageListEntryID(d.Id())
if err != nil {
return err
}
deleteInput := &compute.DeleteImageListEntryInput{
Name: *name,
Version: *version,
}
err = client.DeleteImageListEntry(deleteInput)
if err != nil {
return err
}
return nil
}
func parseOPCImageListEntryID(id string) (*string, *int, error) {
s := strings.Split(id, "|")
name, versionString := s[0], s[1]
version, err := strconv.Atoi(versionString)
if err != nil {
return nil, nil, err
}
return &name, &version, nil
}
func expandOPCImageListEntryMachineImages(d *schema.ResourceData) []string {
machineImages := []string{}
for _, i := range d.Get("machine_images").([]interface{}) {
machineImages = append(machineImages, i.(string))
}
return machineImages
}
func generateOPCImageListEntryID(name string, version int) string {
return fmt.Sprintf("%s|%d", name, version)
}

View File

@ -0,0 +1,161 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCImageListEntry_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageListEntry_basic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListEntryDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckImageListEntryExists,
},
},
})
}
func TestAccOPCImageListEntry_Complete(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageListEntry_Complete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListEntryDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckImageListEntryExists,
},
},
})
}
func TestAccOPCImageListEntry_CompleteExpanded(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageListEntry_CompleteExpanded, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListEntryDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckImageListEntryExists,
},
},
})
}
func testAccCheckImageListEntryExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ImageListEntries()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_image_list_entry" {
continue
}
name, version, err := parseOPCImageListEntryID(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Error parsing the Image List ID: '%s': %+v", rs.Primary.ID, err)
}
input := compute.GetImageListEntryInput{
Name: *name,
Version: *version,
}
if _, err := client.GetImageListEntry(&input); err != nil {
return fmt.Errorf("Error retrieving state of Image List Entry %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckImageListEntryDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ImageListEntries()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_image_list_entry" {
continue
}
name, version, err := parseOPCImageListEntryID(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Error parsing the Image List ID: %+v", err)
}
input := compute.GetImageListEntryInput{
Name: *name,
Version: *version,
}
if info, err := client.GetImageListEntry(&input); err == nil {
return fmt.Errorf("Image List Entry %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccImageListEntry_basic = `
resource "opc_compute_image_list" "test" {
name = "test-acc-image-list-entry-basic-%d"
description = "Acceptance Test TestAccOPCImageListEntry_Basic"
default = 1
}
resource "opc_compute_image_list_entry" "test" {
name = "${opc_compute_image_list.test.name}"
machine_images = [ "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" ]
version = 1
}
`
var testAccImageListEntry_Complete = `
resource "opc_compute_image_list" "test" {
name = "test-acc-image-list-entry-basic-%d"
description = "Acceptance Test TestAccOPCImageListEntry_Basic"
default = 1
}
resource "opc_compute_image_list_entry" "test" {
name = "${opc_compute_image_list.test.name}"
machine_images = [ "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" ]
attributes = "{\"hello\":\"world\"}"
version = 1
}
`
var testAccImageListEntry_CompleteExpanded = `
resource "opc_compute_image_list" "test" {
name = "test-acc-image-list-entry-basic-%d"
description = "Acceptance Test TestAccOPCImageListEntry_Basic"
default = 1
}
resource "opc_compute_image_list_entry" "test" {
name = "${opc_compute_image_list.test.name}"
machine_images = [ "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" ]
attributes = <<JSON
{
"hello": "world"
}
JSON
version = 1
}
`

View File

@ -0,0 +1,98 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCImageList_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageList_basic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckImageListExists,
},
},
})
}
func TestAccOPCImageList_Complete(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccImageList_complete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckImageListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckImageListExists,
},
},
})
}
func testAccCheckImageListExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ImageList()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_image_list" {
continue
}
input := compute.GetImageListInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetImageList(&input); err != nil {
return fmt.Errorf("Error retrieving state of Image List %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckImageListDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).ImageList()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_image_list" {
continue
}
input := compute.GetImageListInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetImageList(&input); err == nil {
return fmt.Errorf("Image List %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccImageList_basic = `
resource "opc_compute_image_list" "test" {
name = "test-acc-image-list-basic-%d"
description = "Image List (Basic)"
}
`
var testAccImageList_complete = `
resource "opc_compute_image_list" "test" {
name = "test-acc-image-list-complete-%d"
description = "Image List (Complete)"
default = 2
}
`

View File

@ -0,0 +1,897 @@
package opc
import (
"bytes"
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceInstance() *schema.Resource {
return &schema.Resource{
Create: resourceInstanceCreate,
Read: resourceInstanceRead,
Delete: resourceInstanceDelete,
Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
combined := strings.Split(d.Id(), "/")
if len(combined) != 2 {
return nil, fmt.Errorf("Invalid ID specified. Must be in the form of instance_name/instance_id. Got: %s", d.Id())
}
d.Set("name", combined[0])
d.SetId(combined[1])
return []*schema.ResourceData{d}, nil
},
},
Schema: map[string]*schema.Schema{
/////////////////////////
// Required Attributes //
/////////////////////////
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"shape": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
/////////////////////////
// Optional Attributes //
/////////////////////////
"instance_attributes": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.ValidateJsonString,
},
"boot_order": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeInt},
},
"hostname": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"image_list": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"label": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"networking_info": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dns": {
// Required for Shared Network Interface, will default if unspecified, however
// Optional for IP Network Interface
Type: schema.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"index": {
Type: schema.TypeInt,
ForceNew: true,
Required: true,
},
"ip_address": {
// Optional, IP Network only
Type: schema.TypeString,
ForceNew: true,
Optional: true,
},
"ip_network": {
// Required for an IP Network Interface
Type: schema.TypeString,
ForceNew: true,
Optional: true,
},
"mac_address": {
// Optional, IP Network Only
Type: schema.TypeString,
ForceNew: true,
Computed: true,
Optional: true,
},
"name_servers": {
// Optional, IP Network + Shared Network
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"nat": {
// Optional for IP Network
// Required for Shared Network
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"search_domains": {
// Optional, IP Network + Shared Network
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"sec_lists": {
// Required, Shared Network only. Will default if unspecified however
Type: schema.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"shared_network": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
},
"vnic": {
// Optional, IP Network only.
Type: schema.TypeString,
ForceNew: true,
Optional: true,
},
"vnic_sets": {
// Optional, IP Network only.
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["index"].(int)))
buf.WriteString(fmt.Sprintf("%s-", m["vnic"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["nat"]))
return hashcode.String(buf.String())
},
},
"reverse_dns": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
},
"ssh_keys": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"storage": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"index": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntBetween(1, 10),
},
"volume": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"tags": tagsForceNewSchema(),
/////////////////////////
// Computed Attributes //
/////////////////////////
"attributes": {
Type: schema.TypeString,
Computed: true,
},
"availability_domain": {
Type: schema.TypeString,
Computed: true,
},
"domain": {
Type: schema.TypeString,
Computed: true,
},
"entry": {
Type: schema.TypeInt,
Computed: true,
},
"fingerprint": {
Type: schema.TypeString,
Computed: true,
},
"image_format": {
Type: schema.TypeString,
Computed: true,
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
},
"placement_requirements": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"platform": {
Type: schema.TypeString,
Computed: true,
},
"priority": {
Type: schema.TypeString,
Computed: true,
},
"quota_reservation": {
Type: schema.TypeString,
Computed: true,
},
"relationships": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"resolvers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"site": {
Type: schema.TypeString,
Computed: true,
},
"start_time": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
"vcable": {
Type: schema.TypeString,
Computed: true,
},
"virtio": {
Type: schema.TypeBool,
Computed: true,
},
"vnc_address": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceInstanceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Instances()
// Get Required Attributes
input := &compute.CreateInstanceInput{
Name: d.Get("name").(string),
Shape: d.Get("shape").(string),
}
// Get optional instance attributes
attributes, attrErr := getInstanceAttributes(d)
if attrErr != nil {
return attrErr
}
if attributes != nil {
input.Attributes = attributes
}
if bootOrder := getIntList(d, "boot_order"); len(bootOrder) > 0 {
input.BootOrder = bootOrder
}
if v, ok := d.GetOk("hostname"); ok {
input.Hostname = v.(string)
}
if v, ok := d.GetOk("image_list"); ok {
input.ImageList = v.(string)
}
if v, ok := d.GetOk("label"); ok {
input.Label = v.(string)
}
interfaces, err := readNetworkInterfacesFromConfig(d)
if err != nil {
return err
}
if interfaces != nil {
input.Networking = interfaces
}
if v, ok := d.GetOk("reverse_dns"); ok {
input.ReverseDNS = v.(bool)
}
if sshKeys := getStringList(d, "ssh_keys"); len(sshKeys) > 0 {
input.SSHKeys = sshKeys
}
storage := getStorageAttachments(d)
if len(storage) > 0 {
input.Storage = storage
}
if tags := getStringList(d, "tags"); len(tags) > 0 {
input.Tags = tags
}
result, err := client.CreateInstance(input)
if err != nil {
return fmt.Errorf("Error creating instance %s: %s", input.Name, err)
}
log.Printf("[DEBUG] Created instance %s: %#v", input.Name, result.ID)
d.SetId(result.ID)
return resourceInstanceRead(d, meta)
}
func resourceInstanceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Instances()
name := d.Get("name").(string)
input := &compute.GetInstanceInput{
ID: d.Id(),
Name: name,
}
log.Printf("[DEBUG] Reading state of instance %s", name)
result, err := client.GetInstance(input)
if err != nil {
// Instance doesn't exist
if compute.WasNotFoundError(err) {
log.Printf("[DEBUG] Instance %s not found", name)
d.SetId("")
return nil
}
return fmt.Errorf("Error reading instance %s: %s", name, err)
}
log.Printf("[DEBUG] Instance '%s' found", name)
// Update attributes
return updateInstanceAttributes(d, result)
}
func updateInstanceAttributes(d *schema.ResourceData, instance *compute.InstanceInfo) error {
d.Set("name", instance.Name)
d.Set("shape", instance.Shape)
if err := setInstanceAttributes(d, instance.Attributes); err != nil {
return err
}
if attrs, ok := d.GetOk("instance_attributes"); ok && attrs != nil {
d.Set("instance_attributes", attrs.(string))
}
if err := setIntList(d, "boot_order", instance.BootOrder); err != nil {
return err
}
d.Set("hostname", instance.Hostname)
d.Set("image_list", instance.ImageList)
d.Set("label", instance.Label)
if err := readNetworkInterfaces(d, instance.Networking); err != nil {
return err
}
d.Set("reverse_dns", instance.ReverseDNS)
if err := setStringList(d, "ssh_keys", instance.SSHKeys); err != nil {
return err
}
if err := readStorageAttachments(d, instance.Storage); err != nil {
return err
}
if err := setStringList(d, "tags", instance.Tags); err != nil {
return err
}
d.Set("availability_domain", instance.AvailabilityDomain)
d.Set("domain", instance.Domain)
d.Set("entry", instance.Entry)
d.Set("fingerprint", instance.Fingerprint)
d.Set("image_format", instance.ImageFormat)
d.Set("ip_address", instance.IPAddress)
if err := setStringList(d, "placement_requirements", instance.PlacementRequirements); err != nil {
return err
}
d.Set("platform", instance.Platform)
d.Set("priority", instance.Priority)
d.Set("quota_reservation", instance.QuotaReservation)
if err := setStringList(d, "relationships", instance.Relationships); err != nil {
return err
}
if err := setStringList(d, "resolvers", instance.Resolvers); err != nil {
return err
}
d.Set("site", instance.Site)
d.Set("start_time", instance.StartTime)
d.Set("state", instance.State)
if err := setStringList(d, "tags", instance.Tags); err != nil {
return err
}
d.Set("vcable", instance.VCableID)
d.Set("virtio", instance.Virtio)
d.Set("vnc_address", instance.VNC)
return nil
}
func resourceInstanceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Instances()
name := d.Get("name").(string)
input := &compute.DeleteInstanceInput{
ID: d.Id(),
Name: name,
}
log.Printf("[DEBUG] Deleting instance %s", name)
if err := client.DeleteInstance(input); err != nil {
return fmt.Errorf("Error deleting instance %s: %s", name, err)
}
return nil
}
func getStorageAttachments(d *schema.ResourceData) []compute.StorageAttachmentInput {
storageAttachments := []compute.StorageAttachmentInput{}
storage := d.Get("storage").(*schema.Set)
for _, i := range storage.List() {
attrs := i.(map[string]interface{})
storageAttachments = append(storageAttachments, compute.StorageAttachmentInput{
Index: attrs["index"].(int),
Volume: attrs["volume"].(string),
})
}
return storageAttachments
}
// Parses instance_attributes from a string to a map[string]interface and returns any errors.
func getInstanceAttributes(d *schema.ResourceData) (map[string]interface{}, error) {
var attrs map[string]interface{}
// Empty instance attributes
attributes, ok := d.GetOk("instance_attributes")
if !ok {
return attrs, nil
}
if err := json.Unmarshal([]byte(attributes.(string)), &attrs); err != nil {
return attrs, fmt.Errorf("Cannot parse attributes as json: %s", err)
}
return attrs, nil
}
// Reads attributes from the returned instance object, and sets the computed attributes string
// as JSON
func setInstanceAttributes(d *schema.ResourceData, attributes map[string]interface{}) error {
// Shouldn't ever get nil attributes on an instance, but protect against the case either way
if attributes == nil {
return nil
}
b, err := json.Marshal(attributes)
if err != nil {
return fmt.Errorf("Error marshalling returned attributes: %s", err)
}
return d.Set("attributes", string(b))
}
// Populates and validates shared network and ip network interfaces to return the of map
// objects needed to create/update an instance's networking_info
func readNetworkInterfacesFromConfig(d *schema.ResourceData) (map[string]compute.NetworkingInfo, error) {
interfaces := make(map[string]compute.NetworkingInfo)
if v, ok := d.GetOk("networking_info"); ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
ni := v.(map[string]interface{})
index, ok := ni["index"].(int)
if !ok {
return nil, fmt.Errorf("Index not specified for network interface: %v", ni)
}
deviceIndex := fmt.Sprintf("eth%d", index)
// Verify that the network interface doesn't already exist
if _, ok := interfaces[deviceIndex]; ok {
return nil, fmt.Errorf("Duplicate Network interface at eth%d already specified", index)
}
// Determine if we're creating a shared network interface or an IP Network interface
info := compute.NetworkingInfo{}
var err error
if ni["shared_network"].(bool) {
// Populate shared network parameters
info, err = readSharedNetworkFromConfig(ni)
// Set 'model' since we're configuring a shared network interface
info.Model = compute.NICDefaultModel
} else {
// Populate IP Network Parameters
info, err = readIPNetworkFromConfig(ni)
}
if err != nil {
return nil, err
}
// And you may find yourself in a beautiful house, with a beautiful wife
// And you may ask yourself, well, how did I get here?
interfaces[deviceIndex] = info
}
}
return interfaces, nil
}
// Reads a networking_info config block as a shared network interface
func readSharedNetworkFromConfig(ni map[string]interface{}) (compute.NetworkingInfo, error) {
info := compute.NetworkingInfo{}
// Validate the shared network
if err := validateSharedNetwork(ni); err != nil {
return info, err
}
// Populate shared network fields; checking type casting
dns := []string{}
if v, ok := ni["dns"]; ok && v != nil {
for _, d := range v.([]interface{}) {
dns = append(dns, d.(string))
}
if len(dns) > 0 {
info.DNS = dns
}
}
if v, ok := ni["model"].(string); ok && v != "" {
info.Model = compute.NICModel(v)
}
nats := []string{}
if v, ok := ni["nat"]; ok && v != nil {
for _, nat := range v.([]interface{}) {
nats = append(nats, nat.(string))
}
if len(nats) > 0 {
info.Nat = nats
}
}
slists := []string{}
if v, ok := ni["sec_lists"]; ok && v != nil {
for _, slist := range v.([]interface{}) {
slists = append(slists, slist.(string))
}
if len(slists) > 0 {
info.SecLists = slists
}
}
nservers := []string{}
if v, ok := ni["name_servers"]; ok && v != nil {
for _, nserver := range v.([]interface{}) {
nservers = append(nservers, nserver.(string))
}
if len(nservers) > 0 {
info.NameServers = nservers
}
}
sdomains := []string{}
if v, ok := ni["search_domains"]; ok && v != nil {
for _, sdomain := range v.([]interface{}) {
sdomains = append(sdomains, sdomain.(string))
}
if len(sdomains) > 0 {
info.SearchDomains = sdomains
}
}
return info, nil
}
// Unfortunately this cannot take place during plan-phase, because we currently cannot have a validation
// function based off of multiple fields in the supplied schema.
func validateSharedNetwork(ni map[string]interface{}) error {
// A Shared Networking Interface MUST have the following attributes set:
// - "nat"
// The following attributes _cannot_ be set for a shared network:
// - "ip_address"
// - "ip_network"
// - "mac_address"
// - "vnic"
// - "vnic_sets"
if _, ok := ni["nat"]; !ok {
return fmt.Errorf("'nat' field needs to be set for a Shared Networking Interface")
}
// Strings only
nilAttrs := []string{
"ip_address",
"ip_network",
"mac_address",
"vnic",
}
for _, v := range nilAttrs {
if d, ok := ni[v]; ok && d.(string) != "" {
return fmt.Errorf("%q field cannot be set in a Shared Networking Interface", v)
}
}
if _, ok := ni["vnic_sets"].([]string); ok {
return fmt.Errorf("%q field cannot be set in a Shared Networking Interface", "vnic_sets")
}
return nil
}
// Populates fields for an IP Network
func readIPNetworkFromConfig(ni map[string]interface{}) (compute.NetworkingInfo, error) {
info := compute.NetworkingInfo{}
// Validate the IP Network
if err := validateIPNetwork(ni); err != nil {
return info, err
}
// Populate fields
if v, ok := ni["ip_network"].(string); ok && v != "" {
info.IPNetwork = v
}
dns := []string{}
if v, ok := ni["dns"]; ok && v != nil {
for _, d := range v.([]interface{}) {
dns = append(dns, d.(string))
}
if len(dns) > 0 {
info.DNS = dns
}
}
if v, ok := ni["ip_address"].(string); ok && v != "" {
info.IPAddress = v
}
if v, ok := ni["mac_address"].(string); ok && v != "" {
info.MACAddress = v
}
nservers := []string{}
if v, ok := ni["name_servers"]; ok && v != nil {
for _, nserver := range v.([]interface{}) {
nservers = append(nservers, nserver.(string))
}
if len(nservers) > 0 {
info.NameServers = nservers
}
}
nats := []string{}
if v, ok := ni["nat"]; ok && v != nil {
for _, nat := range v.([]interface{}) {
nats = append(nats, nat.(string))
}
if len(nats) > 0 {
info.Nat = nats
}
}
sdomains := []string{}
if v, ok := ni["search_domains"]; ok && v != nil {
for _, sdomain := range v.([]interface{}) {
sdomains = append(sdomains, sdomain.(string))
}
if len(sdomains) > 0 {
info.SearchDomains = sdomains
}
}
if v, ok := ni["vnic"].(string); ok && v != "" {
info.Vnic = v
}
vnicSets := []string{}
if v, ok := ni["vnic_sets"]; ok && v != nil {
for _, vnic := range v.([]interface{}) {
vnicSets = append(vnicSets, vnic.(string))
}
if len(vnicSets) > 0 {
info.VnicSets = vnicSets
}
}
return info, nil
}
// Validates an IP Network config block
func validateIPNetwork(ni map[string]interface{}) error {
// An IP Networking Interface MUST have the following attributes set:
// - "ip_network"
// Required to be set
if d, ok := ni["ip_network"]; !ok || d.(string) == "" {
return fmt.Errorf("'ip_network' field is required for an IP Network interface")
}
return nil
}
// Reads network interfaces from the config
func readNetworkInterfaces(d *schema.ResourceData, ifaces map[string]compute.NetworkingInfo) error {
result := make([]map[string]interface{}, 0)
// Nil check for import case
if ifaces == nil {
return d.Set("networking_info", result)
}
for index, iface := range ifaces {
res := make(map[string]interface{})
// The index returned from the SDK holds the full device_index from the instance.
// For users convenience, we simply allow them to specify the integer equivalent of the device_index
// so a user could implement several network interfaces via `count`.
// Convert the full device_index `ethN` to `N` as an integer.
index := strings.TrimPrefix(index, "eth")
indexInt, err := strconv.Atoi(index)
if err != nil {
return err
}
res["index"] = indexInt
// Set the proper attributes for this specific network interface
if iface.DNS != nil {
res["dns"] = iface.DNS
}
if iface.IPAddress != "" {
res["ip_address"] = iface.IPAddress
}
if iface.IPNetwork != "" {
res["ip_network"] = iface.IPNetwork
}
if iface.MACAddress != "" {
res["mac_address"] = iface.MACAddress
}
if iface.Model != "" {
// Model can only be set on Shared networks
res["shared_network"] = true
}
if iface.NameServers != nil {
res["name_servers"] = iface.NameServers
}
if iface.Nat != nil {
res["nat"] = iface.Nat
}
if iface.SearchDomains != nil {
res["search_domains"] = iface.SearchDomains
}
if iface.SecLists != nil {
res["sec_lists"] = iface.SecLists
}
if iface.Vnic != "" {
res["vnic"] = iface.Vnic
// VNIC can only be set on an IP Network
res["shared_network"] = false
}
if iface.VnicSets != nil {
res["vnic_sets"] = iface.VnicSets
}
result = append(result, res)
}
return d.Set("networking_info", result)
}
// Flattens the returned slice of storage attachments to a map
func readStorageAttachments(d *schema.ResourceData, attachments []compute.StorageAttachment) error {
result := make([]map[string]interface{}, 0)
if attachments == nil || len(attachments) == 0 {
return d.Set("storage", nil)
}
for _, attachment := range attachments {
res := make(map[string]interface{})
res["index"] = attachment.Index
res["volume"] = attachment.StorageVolumeName
res["name"] = attachment.Name
result = append(result, res)
}
return d.Set("storage", result)
}

View File

@ -0,0 +1,273 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCInstance_basic(t *testing.T) {
resName := "opc_compute_instance.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceBasic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckInstanceExists,
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("acc-test-instance-%d", rInt)),
resource.TestCheckResourceAttr(resName, "label", "TestAccOPCInstance_basic"),
),
},
},
})
}
func TestAccOPCInstance_sharedNetworking(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_instance.test"
dataName := "data.opc_compute_network_interface.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceSharedNetworking(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckInstanceExists,
resource.TestCheckResourceAttrSet(resName, "id"),
resource.TestCheckResourceAttrSet(resName, "availability_domain"),
resource.TestCheckResourceAttrSet(resName, "domain"),
resource.TestCheckResourceAttrSet(resName, "hostname"),
resource.TestCheckResourceAttrSet(resName, "ip_address"),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("acc-test-instance-%d", rInt)),
resource.TestCheckResourceAttr(resName, "networking_info.#", "1"),
// Default Placement Reqs
resource.TestCheckResourceAttr(resName, "placement_requirements.#", "2"),
resource.TestCheckResourceAttr(resName, "placement_requirements.0", "/system/compute/allow_instances"),
resource.TestCheckResourceAttr(resName, "placement_requirements.1", "/system/compute/placement/default"),
resource.TestCheckResourceAttr(resName, "platform", "linux"),
resource.TestCheckResourceAttr(resName, "priority", "/oracle/public/default"),
resource.TestCheckResourceAttr(resName, "reverse_dns", "true"),
resource.TestCheckResourceAttr(resName, "state", "running"),
resource.TestCheckResourceAttr(resName, "tags.#", "2"),
resource.TestCheckResourceAttrSet(resName, "vcable"),
resource.TestCheckResourceAttr(resName, "virtio", "false"),
// Check Data Source to validate networking attributes
resource.TestCheckResourceAttr(dataName, "shared_network", "true"),
resource.TestCheckResourceAttr(dataName, "nat.#", "1"),
resource.TestCheckResourceAttr(dataName, "sec_lists.#", "1"),
resource.TestCheckResourceAttr(dataName, "name_servers.#", "0"),
resource.TestCheckResourceAttr(dataName, "vnic_sets.#", "0"),
),
},
},
})
}
func TestAccOPCInstance_ipNetwork(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_instance.test"
dataName := "data.opc_compute_network_interface.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceIPNetworking(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckInstanceExists,
resource.TestCheckResourceAttrSet(resName, "id"),
resource.TestCheckResourceAttrSet(resName, "availability_domain"),
resource.TestCheckResourceAttrSet(resName, "domain"),
resource.TestCheckResourceAttrSet(resName, "ip_address"),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("acc-test-instance-%d", rInt)),
resource.TestCheckResourceAttr(resName, "networking_info.#", "1"),
// Default Placement Reqs
resource.TestCheckResourceAttr(resName, "placement_requirements.#", "2"),
resource.TestCheckResourceAttr(resName, "placement_requirements.0", "/system/compute/allow_instances"),
resource.TestCheckResourceAttr(resName, "placement_requirements.1", "/system/compute/placement/default"),
resource.TestCheckResourceAttr(resName, "platform", "linux"),
resource.TestCheckResourceAttr(resName, "priority", "/oracle/public/default"),
resource.TestCheckResourceAttr(resName, "reverse_dns", "true"),
resource.TestCheckResourceAttr(resName, "state", "running"),
resource.TestCheckResourceAttr(resName, "virtio", "false"),
// Check Data Source to validate networking attributes
resource.TestCheckResourceAttr(dataName, "ip_network", fmt.Sprintf("testing-ip-network-%d", rInt)),
resource.TestCheckResourceAttr(dataName, "vnic", fmt.Sprintf("ip-network-test-%d", rInt)),
resource.TestCheckResourceAttr(dataName, "shared_network", "false"),
),
},
},
})
}
func TestAccOPCInstance_storage(t *testing.T) {
resName := "opc_compute_instance.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceStorage(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckInstanceExists,
resource.TestCheckResourceAttr(resName, "storage.#", "2"),
),
},
},
})
}
func testAccOPCCheckInstanceExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).Instances()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_instance" {
continue
}
input := &compute.GetInstanceInput{
ID: rs.Primary.ID,
Name: rs.Primary.Attributes["name"],
}
_, err := client.GetInstance(input)
if err != nil {
return fmt.Errorf("Error retrieving state of Instance %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckInstanceDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).Instances()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_instance" {
continue
}
input := &compute.GetInstanceInput{
ID: rs.Primary.ID,
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetInstance(input); err == nil {
return fmt.Errorf("Instance %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccInstanceBasic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_instance" "test" {
name = "acc-test-instance-%d"
label = "TestAccOPCInstance_basic"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
instance_attributes = <<JSON
{
"foo": "bar"
}
JSON
}`, rInt)
}
func testAccInstanceSharedNetworking(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_instance" "test" {
name = "acc-test-instance-%d"
label = "TestAccOPCInstance_sharedNetworking"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
tags = ["tag1", "tag2"]
networking_info {
index = 0
nat = ["ippool:/oracle/public/ippool"]
shared_network = true
}
}
data "opc_compute_network_interface" "test" {
instance_name = "${opc_compute_instance.test.name}"
instance_id = "${opc_compute_instance.test.id}"
interface = "eth0"
}
`, rInt)
}
func testAccInstanceIPNetworking(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-ip-network-%d"
description = "testing-ip-network-instance"
ip_address_prefix = "10.1.12.0/24"
}
resource "opc_compute_instance" "test" {
name = "acc-test-instance-%d"
label = "TestAccOPCInstance_ipNetwork"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "ip-network-test-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "test" {
instance_id = "${opc_compute_instance.test.id}"
instance_name = "${opc_compute_instance.test.name}"
interface = "eth0"
}
`, rInt, rInt, rInt)
}
func testAccInstanceStorage(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_storage_volume" "foo" {
name = "acc-test-instance-%d"
size = 1
}
resource "opc_compute_storage_volume" "bar" {
name = "acc-test-instance-2-%d"
size = 1
}
resource "opc_compute_instance" "test" {
name = "acc-test-instance-%d"
label = "TestAccOPCInstance_basic"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
storage {
volume = "${opc_compute_storage_volume.foo.name}"
index = 1
}
storage {
volume = "${opc_compute_storage_volume.bar.name}"
index = 2
}
}`, rInt, rInt, rInt)
}

View File

@ -0,0 +1,156 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPAddressAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPAddressAssociationCreate,
Read: resourceOPCIPAddressAssociationRead,
Update: resourceOPCIPAddressAssociationUpdate,
Delete: resourceOPCIPAddressAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ip_address_reservation": {
Type: schema.TypeString,
Optional: true,
},
"vnic": {
Type: schema.TypeString,
Optional: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"tags": tagsOptionalSchema(),
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCIPAddressAssociationCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressAssociations()
input := compute.CreateIPAddressAssociationInput{
Name: d.Get("name").(string),
}
if ipAddressReservation, ok := d.GetOk("ip_address_reservation"); ok {
input.IPAddressReservation = ipAddressReservation.(string)
}
if vnic, ok := d.GetOk("vnic"); ok {
input.Vnic = vnic.(string)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateIPAddressAssociation(&input)
if err != nil {
return fmt.Errorf("Error creating IP Address Association: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressAssociationRead(d, meta)
}
func resourceOPCIPAddressAssociationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressAssociations()
name := d.Id()
getInput := compute.GetIPAddressAssociationInput{
name,
}
result, err := client.GetIPAddressAssociation(&getInput)
if err != nil {
// IP Address Association does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IP Address Association %s: %s", name, err)
}
if result == nil {
d.SetId("")
return fmt.Errorf("Error reading IP Address Association %s: %s", name, err)
}
d.Set("name", result.Name)
d.Set("ip_address_reservation", result.IPAddressReservation)
d.Set("vnic", result.Vnic)
d.Set("description", result.Description)
d.Set("uri", result.Uri)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCIPAddressAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressAssociations()
input := compute.UpdateIPAddressAssociationInput{
Name: d.Get("name").(string),
}
if ipAddressReservation, ok := d.GetOk("ip_address_reservation"); ok {
input.IPAddressReservation = ipAddressReservation.(string)
}
if vnic, ok := d.GetOk("vnic"); ok {
input.Vnic = vnic.(string)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateIPAddressAssociation(&input)
if err != nil {
return fmt.Errorf("Error updating IP Address Association: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressAssociationRead(d, meta)
}
func resourceOPCIPAddressAssociationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressAssociations()
name := d.Id()
input := compute.DeleteIPAddressAssociationInput{
Name: name,
}
if err := client.DeleteIPAddressAssociation(&input); err != nil {
return fmt.Errorf("Error deleting IP Address Association: %s", err)
}
return nil
}

View File

@ -0,0 +1,155 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPAddressAssociation_Basic(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "opc_compute_ip_address_association.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPAddressAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccIPAddressAssociationBasic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckIPAddressAssociationExists,
resource.TestCheckResourceAttr(
resourceName, "tags.#", "2"),
),
},
{
Config: testAccIPAddressAssociationBasic_Update(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
resourceName, "tags.#", "1"),
),
},
},
})
}
func TestAccOPCIPAddressAssociation_Full(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "opc_compute_ip_address_association.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPAddressAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccIPAddressAssociationFull(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckIPAddressAssociationExists,
resource.TestCheckResourceAttr(
resourceName, "vnic", fmt.Sprintf("test-vnic-data-%d", rInt)),
resource.TestCheckResourceAttr(
resourceName, "ip_address_reservation", fmt.Sprintf("testing-ip-address-association-%d", rInt)),
),
},
},
})
}
func testAccCheckIPAddressAssociationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_association" {
continue
}
input := compute.GetIPAddressAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPAddressAssociation(&input); err != nil {
return fmt.Errorf("Error retrieving state of IP Address Association %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckIPAddressAssociationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_association" {
continue
}
input := compute.GetIPAddressAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPAddressAssociation(&input); err == nil {
return fmt.Errorf("IP Address Association %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccIPAddressAssociationBasic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_address_association" "test" {
name = "testing-acc-%d"
description = "acctesting ip address association test %d"
tags = ["tag1", "tag2"]
}`, rInt, rInt)
}
func testAccIPAddressAssociationBasic_Update(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_address_association" "test" {
name = "testing-acc-%d"
description = "acctesting ip address association test updated %d"
tags = ["tag1"]
}`, rInt, rInt)
}
func testAccIPAddressAssociationFull(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-vnic-data-%d"
description = "testing-ip-address-association"
ip_address_prefix = "10.1.13.0/24"
}
resource "opc_compute_instance" "test" {
name = "test-%d"
label = "test"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-data-%d"
shared_network = false
mac_address = "02:5a:cd:ec:2e:4c"
}
}
data "opc_compute_network_interface" "eth0" {
instance_name = "${opc_compute_instance.test.name}"
instance_id = "${opc_compute_instance.test.id}"
interface = "eth0"
}
resource "opc_compute_ip_address_reservation" "test" {
name = "testing-ip-address-association-%d"
description = "testing-desc-%d"
ip_address_pool = "public-ippool"
}
resource "opc_compute_ip_address_association" "test" {
name = "testing-acc-%d"
ip_address_reservation = "${opc_compute_ip_address_reservation.test.name}"
vnic = "${data.opc_compute_network_interface.eth0.vnic}"
description = "acctesting ip address association test %d"
tags = ["tag1", "tag2"]
}`, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,147 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPAddressPrefixSet() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPAddressPrefixSetCreate,
Read: resourceOPCIPAddressPrefixSetRead,
Update: resourceOPCIPAddressPrefixSetUpdate,
Delete: resourceOPCIPAddressPrefixSetDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"prefixes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validateIPPrefixCIDR,
},
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"tags": tagsOptionalSchema(),
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCIPAddressPrefixSetCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressPrefixSets()
input := compute.CreateIPAddressPrefixSetInput{
Name: d.Get("name").(string),
}
prefixes := getStringList(d, "prefixes")
if len(prefixes) != 0 {
input.IPAddressPrefixes = prefixes
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateIPAddressPrefixSet(&input)
if err != nil {
return fmt.Errorf("Error creating IP Address Prefix Set: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressPrefixSetRead(d, meta)
}
func resourceOPCIPAddressPrefixSetRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressPrefixSets()
getInput := compute.GetIPAddressPrefixSetInput{
Name: d.Id(),
}
result, err := client.GetIPAddressPrefixSet(&getInput)
if err != nil {
// IP Address Prefix Set does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IP Address Prefix Set %s: %s", d.Id(), err)
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("uri", result.Uri)
if err := setStringList(d, "prefixes", result.IPAddressPrefixes); err != nil {
return err
}
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCIPAddressPrefixSetUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressPrefixSets()
input := compute.UpdateIPAddressPrefixSetInput{
Name: d.Get("name").(string),
}
prefixes := getStringList(d, "prefixes")
if len(prefixes) != 0 {
input.IPAddressPrefixes = prefixes
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateIPAddressPrefixSet(&input)
if err != nil {
return fmt.Errorf("Error updating IP Address Prefix Set: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressPrefixSetRead(d, meta)
}
func resourceOPCIPAddressPrefixSetDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressPrefixSets()
name := d.Id()
input := compute.DeleteIPAddressPrefixSetInput{
Name: name,
}
if err := client.DeleteIPAddressPrefixSet(&input); err != nil {
return fmt.Errorf("Error deleting IP Address Prefix Set: %s", err)
}
return nil
}

View File

@ -0,0 +1,100 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPAddressPrefixSet_Basic(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "opc_compute_ip_address_prefix_set.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPAddressPrefixSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccIPAddressPrefixSetBasic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckIPAddressPrefixSetExists,
resource.TestCheckResourceAttr(
resourceName, "tags.#", "2"),
resource.TestCheckResourceAttr(
resourceName, "prefixes.#", "2"),
),
},
{
Config: testAccIPAddressPrefixSetBasic_Update(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
resourceName, "tags.#", "1"),
resource.TestCheckResourceAttr(
resourceName, "prefixes.0", "171.120.0.0/24"),
),
},
},
})
}
func testAccCheckIPAddressPrefixSetExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressPrefixSets()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_prefix_set" {
continue
}
input := compute.GetIPAddressPrefixSetInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPAddressPrefixSet(&input); err != nil {
return fmt.Errorf("Error retrieving state of IP Address Prefix Set %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckIPAddressPrefixSetDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressPrefixSets()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_prefix_set" {
continue
}
input := compute.GetIPAddressPrefixSetInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPAddressPrefixSet(&input); err == nil {
return fmt.Errorf("IP Address Prefix Set %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccIPAddressPrefixSetBasic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_address_prefix_set" "test" {
name = "testing-acc-%d"
prefixes = ["172.120.0.0/24", "192.168.0.0/16"]
description = "acctesting ip address prefix test %d"
tags = ["tag1", "tag2"]
}`, rInt, rInt)
}
func testAccIPAddressPrefixSetBasic_Update(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_address_prefix_set" "test" {
name = "testing-acc-%d"
description = "acctesting ip address prefix test updated %d"
prefixes = ["171.120.0.0/24", "192.168.0.0/16"]
tags = ["tag1"]
}`, rInt, rInt)
}

View File

@ -0,0 +1,137 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceOPCIPAddressReservation() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPAddressReservationCreate,
Read: resourceOPCIPAddressReservationRead,
Update: resourceOPCIPAddressReservationUpdate,
Delete: resourceOPCIPAddressReservationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ip_address_pool": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(compute.PublicIPAddressPool),
string(compute.PrivateIPAddressPool),
}, true),
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"tags": tagsOptionalSchema(),
"ip_address": {
Type: schema.TypeString,
Computed: true,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCIPAddressReservationCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressReservations()
input := compute.CreateIPAddressReservationInput{
Name: d.Get("name").(string),
IPAddressPool: d.Get("ip_address_pool").(string),
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateIPAddressReservation(&input)
if err != nil {
return fmt.Errorf("Error creating IP Address Reservation: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressReservationRead(d, meta)
}
func resourceOPCIPAddressReservationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressReservations()
getInput := compute.GetIPAddressReservationInput{
Name: d.Id(),
}
result, err := client.GetIPAddressReservation(&getInput)
if err != nil {
// IP Address Reservation does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading ip address reservation %s: %s", d.Id(), err)
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("ip_address_pool", result.IPAddressPool)
d.Set("uri", result.Uri)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCIPAddressReservationUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressReservations()
input := compute.UpdateIPAddressReservationInput{
Name: d.Get("name").(string),
IPAddressPool: d.Get("ip_address_pool").(string),
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateIPAddressReservation(&input)
if err != nil {
return fmt.Errorf("Error updating IP Address Reservation: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPAddressReservationRead(d, meta)
}
func resourceOPCIPAddressReservationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAddressReservations()
name := d.Id()
input := compute.DeleteIPAddressReservationInput{
Name: name,
}
if err := client.DeleteIPAddressReservation(&input); err != nil {
return fmt.Errorf("Error deleting IP Address Reservation: %+v", err)
}
return nil
}

View File

@ -0,0 +1,77 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPAddressReservation_Basic(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_ip_address_reservation.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckIPAddressReservationDestroy,
Steps: []resource.TestStep{
{
Config: testAccOPCIPAddressReservationConfig_Basic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckIPAddressReservationExists,
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-ip-address-reservation-%d", rInt)),
),
},
},
})
}
func testAccOPCCheckIPAddressReservationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressReservations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_reservation" {
continue
}
input := compute.GetIPAddressReservationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPAddressReservation(&input); err != nil {
return fmt.Errorf("Error retrieving state of IP Address Reservation %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckIPAddressReservationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAddressReservations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_address_reservation" {
continue
}
input := compute.GetIPAddressReservationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPAddressReservation(&input); err == nil {
return fmt.Errorf("IP Address Reservation %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccOPCIPAddressReservationConfig_Basic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_address_reservation" "test" {
name = "testing-ip-address-reservation-%d"
description = "testing-desc-%d"
ip_address_pool = "public-ippool"
}`, rInt, rInt)
}

View File

@ -0,0 +1,96 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPAssociationCreate,
Read: resourceOPCIPAssociationRead,
Delete: resourceOPCIPAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"vcable": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"parent_pool": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceOPCIPAssociationCreate(d *schema.ResourceData, meta interface{}) error {
vCable := d.Get("vcable").(string)
parentPool := d.Get("parent_pool").(string)
client := meta.(*compute.Client).IPAssociations()
input := compute.CreateIPAssociationInput{
ParentPool: parentPool,
VCable: vCable,
}
info, err := client.CreateIPAssociation(&input)
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)
return resourceOPCIPAssociationRead(d, meta)
}
func resourceOPCIPAssociationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAssociations()
name := d.Id()
input := compute.GetIPAssociationInput{
Name: name,
}
result, err := client.GetIPAssociation(&input)
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)
}
d.Set("name", result.Name)
d.Set("parent_pool", result.ParentPool)
d.Set("vcable", result.VCable)
return nil
}
func resourceOPCIPAssociationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPAssociations()
name := d.Id()
input := compute.DeleteIPAssociationInput{
Name: name,
}
if err := client.DeleteIPAssociation(&input); err != nil {
return fmt.Errorf("Error deleting ip association '%s': %s", name, err)
}
return nil
}

View File

@ -0,0 +1,88 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPAssociation_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPAssociationBasic, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckIPAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckIPAssociationExists,
),
},
},
})
}
func testAccOPCCheckIPAssociationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_association" {
continue
}
input := compute.GetIPAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPAssociation(&input); err != nil {
return fmt.Errorf("Error retrieving state of IP Association %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckIPAssociationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_association" {
continue
}
input := compute.GetIPAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPAssociation(&input); err == nil {
return fmt.Errorf("IP Association %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccIPAssociationBasic = `
resource "opc_compute_instance" "test" {
name = "test-acc-ip-ass-instance-%d"
label = "testAccIPAssociationBasic"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
}
resource "opc_compute_ip_reservation" "test" {
name = "test-acc-ip-ass-reservation-%d"
parent_pool = "/oracle/public/ippool"
permanent = true
}
resource "opc_compute_ip_association" "test" {
vcable = "${opc_compute_instance.test.vcable}"
parent_pool = "ipreservation:${opc_compute_ip_reservation.test.name}"
}
`

View File

@ -0,0 +1,179 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPNetwork() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPNetworkCreate,
Read: resourceOPCIPNetworkRead,
Update: resourceOPCIPNetworkUpdate,
Delete: resourceOPCIPNetworkDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"ip_address_prefix": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateIPPrefixCIDR,
},
"ip_network_exchange": {
Type: schema.TypeString,
Optional: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"public_napt_enabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsOptionalSchema(),
},
}
}
func resourceOPCIPNetworkCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworks()
// Get required attributes
name := d.Get("name").(string)
ipPrefix := d.Get("ip_address_prefix").(string)
// public_napt_enabled is not required, but bool type allows it to be unspecified
naptEnabled := d.Get("public_napt_enabled").(bool)
input := &compute.CreateIPNetworkInput{
Name: name,
IPAddressPrefix: ipPrefix,
PublicNaptEnabled: naptEnabled,
}
// Get Optional attributes
if desc, ok := d.GetOk("description"); ok && desc != nil {
input.Description = desc.(string)
}
if ipEx, ok := d.GetOk("ip_network_exchange"); ok && ipEx != nil {
input.IPNetworkExchange = ipEx.(string)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
info, err := client.CreateIPNetwork(input)
if err != nil {
return fmt.Errorf("Error creating IP Network '%s': %v", name, err)
}
d.SetId(info.Name)
return resourceOPCIPNetworkRead(d, meta)
}
func resourceOPCIPNetworkRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworks()
name := d.Id()
input := &compute.GetIPNetworkInput{
Name: name,
}
res, err := client.GetIPNetwork(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IP Network '%s': %v", name, err)
}
d.Set("name", res.Name)
d.Set("ip_address_prefix", res.IPAddressPrefix)
d.Set("ip_network_exchanged", res.IPNetworkExchange)
d.Set("description", res.Description)
d.Set("public_napt_enabled", res.PublicNaptEnabled)
d.Set("uri", res.Uri)
if err := setStringList(d, "tags", res.Tags); err != nil {
return err
}
return nil
}
func resourceOPCIPNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworks()
// Get required attributes
name := d.Get("name").(string)
ipPrefix := d.Get("ip_address_prefix").(string)
// public_napt_enabled is not required, but bool type allows it to be unspecified
naptEnabled := d.Get("public_napt_enabled").(bool)
input := &compute.UpdateIPNetworkInput{
Name: name,
IPAddressPrefix: ipPrefix,
PublicNaptEnabled: naptEnabled,
}
// Get Optional attributes
desc, descOk := d.GetOk("description")
if descOk {
input.Description = desc.(string)
}
ipEx, ipExOk := d.GetOk("ip_network_exchange")
if ipExOk {
input.IPNetworkExchange = ipEx.(string)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
info, err := client.UpdateIPNetwork(input)
if err != nil {
return fmt.Errorf("Error updating IP Network '%s': %v", name, err)
}
d.SetId(info.Name)
return resourceOPCIPNetworkRead(d, meta)
}
func resourceOPCIPNetworkDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworks()
name := d.Id()
input := &compute.DeleteIPNetworkInput{
Name: name,
}
if err := client.DeleteIPNetwork(input); err != nil {
return fmt.Errorf("Error deleting IP Network '%s': %v", name, err)
}
return nil
}

View File

@ -0,0 +1,105 @@
package opc
import (
"fmt"
"log"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPNetworkExchange() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPNetworkExchangeCreate,
Read: resourceOPCIPNetworkExchangeRead,
Delete: resourceOPCIPNetworkExchangeDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"tags": tagsForceNewSchema(),
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCIPNetworkExchangeCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworkExchanges()
input := compute.CreateIPNetworkExchangeInput{
Name: d.Get("name").(string),
}
log.Printf("[DEBUG] Creating ip network exchange '%s'", input.Name)
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateIPNetworkExchange(&input)
if err != nil {
return fmt.Errorf("Error creating IP Network Exchange: %s", err)
}
d.SetId(info.Name)
return resourceOPCIPNetworkExchangeRead(d, meta)
}
func resourceOPCIPNetworkExchangeRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworkExchanges()
log.Printf("[DEBUG] Reading state of IP Network Exchange %s", d.Id())
getInput := compute.GetIPNetworkExchangeInput{
Name: d.Id(),
}
result, err := client.GetIPNetworkExchange(&getInput)
if err != nil {
// IP NetworkExchange does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading ip network exchange %s: %s", d.Id(), err)
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("uri", result.Uri)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCIPNetworkExchangeDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).IPNetworkExchanges()
name := d.Id()
log.Printf("[DEBUG] Deleting IP Network Exchange '%s'", name)
input := compute.DeleteIPNetworkExchangeInput{
Name: name,
}
if err := client.DeleteIPNetworkExchange(&input); err != nil {
return fmt.Errorf("Error deleting IP Network Exchange '%s': %+v", name, err)
}
return nil
}

View File

@ -0,0 +1,73 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPNetworkExchange_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPNetworkExchangeBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPNetworkExchangeDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckIPNetworkExchangeExists,
},
},
})
}
func testAccCheckIPNetworkExchangeExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPNetworkExchanges()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_network_exchange" {
continue
}
input := compute.GetIPNetworkExchangeInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPNetworkExchange(&input); err != nil {
return fmt.Errorf("Error retrieving state of ip network exchange %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckIPNetworkExchangeDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPNetworkExchanges()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_network_exchange" {
continue
}
input := compute.GetIPNetworkExchangeInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPNetworkExchange(&input); err == nil {
return fmt.Errorf("IPNetworkExchange %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccIPNetworkExchangeBasic = `
resource "opc_compute_ip_network_exchange" "test" {
name = "test_ip_network_exchange-%d"
description = "test ip network exchange"
}
`

View File

@ -0,0 +1,115 @@
package opc
import (
"fmt"
"regexp"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCIPNetwork_Basic(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_ip_network.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resName, testAccOPCCheckIPNetworkDestroyed),
Steps: []resource.TestStep{
{
Config: testAccOPCIPNetworkConfig_Basic(rInt),
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(resName, testAccOPCCheckIPNetworkExists),
resource.TestCheckResourceAttr(resName, "ip_address_prefix", "10.0.12.0/24"),
resource.TestCheckResourceAttr(resName, "public_napt_enabled", "false"),
resource.TestCheckResourceAttr(resName, "description", fmt.Sprintf("testing-desc-%d", rInt)),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-ip-network-%d", rInt)),
resource.TestMatchResourceAttr(resName, "uri", regexp.MustCompile("testing-ip-network")),
),
},
},
})
}
func TestAccOPCIPNetwork_Update(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_ip_network.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(resName, testAccOPCCheckIPNetworkDestroyed),
Steps: []resource.TestStep{
{
Config: testAccOPCIPNetworkConfig_Basic(rInt),
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(resName, testAccOPCCheckIPNetworkExists),
resource.TestCheckResourceAttr(resName, "ip_address_prefix", "10.0.12.0/24"),
resource.TestCheckResourceAttr(resName, "public_napt_enabled", "false"),
resource.TestCheckResourceAttr(resName, "description", fmt.Sprintf("testing-desc-%d", rInt)),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-ip-network-%d", rInt)),
resource.TestMatchResourceAttr(resName, "uri", regexp.MustCompile("testing-ip-network")),
),
},
{
Config: testAccOPCIPNetworkConfig_BasicUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(resName, testAccOPCCheckIPNetworkExists),
resource.TestCheckResourceAttr(resName, "ip_address_prefix", "10.0.12.0/24"),
resource.TestCheckResourceAttr(resName, "public_napt_enabled", "true"),
resource.TestCheckResourceAttr(resName, "description", fmt.Sprintf("testing-desc-%d", rInt)),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-ip-network-%d", rInt)),
),
},
},
})
}
func testAccOPCIPNetworkConfig_Basic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "test" {
name = "testing-ip-network-%d"
description = "testing-desc-%d"
ip_address_prefix = "10.0.12.0/24"
}`, rInt, rInt)
}
func testAccOPCIPNetworkConfig_BasicUpdate(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "test" {
name = "testing-ip-network-%d"
description = "testing-desc-%d"
ip_address_prefix = "10.0.12.0/24"
public_napt_enabled = true
}`, rInt, rInt)
}
func testAccOPCCheckIPNetworkExists(state *OPCResourceState) error {
name := state.Attributes["name"]
input := &compute.GetIPNetworkInput{
Name: name,
}
if _, err := state.Client.IPNetworks().GetIPNetwork(input); err != nil {
return fmt.Errorf("Error retrieving state of IP Network '%s': %v", name, err)
}
return nil
}
func testAccOPCCheckIPNetworkDestroyed(state *OPCResourceState) error {
name := state.Attributes["name"]
input := &compute.GetIPNetworkInput{
Name: name,
}
if info, _ := state.Client.IPNetworks().GetIPNetwork(input); info != nil {
return fmt.Errorf("IP Network '%s' still exists: %+v", name, info)
}
return nil
}

View File

@ -0,0 +1,117 @@
package opc
import (
"fmt"
"log"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCIPReservation() *schema.Resource {
return &schema.Resource{
Create: resourceOPCIPReservationCreate,
Read: resourceOPCIPReservationRead,
Delete: resourceOPCIPReservationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"permanent": {
Type: schema.TypeBool,
Required: true,
ForceNew: true,
},
"parent_pool": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tagsForceNewSchema(),
"ip": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCIPReservationCreate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
reservation := compute.CreateIPReservationInput{
Name: d.Get("name").(string),
ParentPool: compute.IPReservationPool(d.Get("parent_pool").(string)),
Permanent: d.Get("permanent").(bool),
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
reservation.Tags = tags
}
log.Printf("[DEBUG] Creating ip reservation from parent_pool %s with tags=%s",
reservation.ParentPool, reservation.Tags)
client := meta.(*compute.Client).IPReservations()
info, err := client.CreateIPReservation(&reservation)
if err != nil {
return fmt.Errorf("Error creating ip reservation from parent_pool %s with tags=%s: %s",
reservation.ParentPool, reservation.Tags, err)
}
d.SetId(info.Name)
return resourceOPCIPReservationRead(d, meta)
}
func resourceOPCIPReservationRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).IPReservations()
log.Printf("[DEBUG] Reading state of ip reservation %s", d.Id())
getInput := compute.GetIPReservationInput{
Name: d.Id(),
}
result, err := client.GetIPReservation(&getInput)
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", d.Id(), err)
}
log.Printf("[DEBUG] Read state of ip reservation %s: %#v", d.Id(), result)
d.Set("name", result.Name)
d.Set("parent_pool", result.ParentPool)
d.Set("permanent", result.Permanent)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
d.Set("ip", result.IP)
return nil
}
func resourceOPCIPReservationDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).IPReservations()
log.Printf("[DEBUG] Deleting ip reservation %s", d.Id())
input := compute.DeleteIPReservationInput{
Name: d.Id(),
}
if err := client.DeleteIPReservation(&input); err != nil {
return fmt.Errorf("Error deleting ip reservation %s", d.Id())
}
return nil
}

View File

@ -0,0 +1,75 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCIPReservation_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccIPReservationBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIPReservationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckIPReservationExists,
},
},
})
}
func testAccCheckIPReservationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPReservations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_reservation" {
continue
}
input := compute.GetIPReservationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetIPReservation(&input); err != nil {
return fmt.Errorf("Error retrieving state of IP Reservation %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckIPReservationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).IPReservations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ip_reservation" {
continue
}
input := compute.GetIPReservationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetIPReservation(&input); err == nil {
return fmt.Errorf("IP Reservation %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccIPReservationBasic = `
resource "opc_compute_ip_reservation" "test" {
name = "acc-test-ip-reservation-%d"
parent_pool = "/oracle/public/ippool"
permanent = true
}
`

View File

@ -0,0 +1,176 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCRoute() *schema.Resource {
return &schema.Resource{
Create: resourceOPCRouteCreate,
Read: resourceOPCRouteRead,
Update: resourceOPCRouteUpdate,
Delete: resourceOPCRouteDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"admin_distance": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validateAdminDistance,
},
"ip_address_prefix": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateIPPrefixCIDR,
},
"next_hop_vnic_set": {
Type: schema.TypeString,
Required: true,
},
"tags": tagsOptionalSchema(),
},
}
}
func resourceOPCRouteCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Routes()
// Get Required attributes
name := d.Get("name").(string)
ipPrefix := d.Get("ip_address_prefix").(string)
nextHop := d.Get("next_hop_vnic_set").(string)
// Start populating input struct
input := &compute.CreateRouteInput{
Name: name,
IPAddressPrefix: ipPrefix,
NextHopVnicSet: nextHop,
}
// Get Optional Attributes
desc, descOk := d.GetOk("description")
if descOk {
input.Description = desc.(string)
}
dist, distOk := d.GetOk("admin_distance")
if distOk {
input.AdminDistance = dist.(int)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
// Create Route
info, err := client.CreateRoute(input)
if err != nil {
return fmt.Errorf("Error creating route '%s': %v", name, err)
}
d.SetId(info.Name)
return resourceOPCRouteRead(d, meta)
}
func resourceOPCRouteRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Routes()
name := d.Id()
input := &compute.GetRouteInput{
Name: name,
}
res, err := client.GetRoute(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading route '%s': %v", name, err)
}
d.Set("name", res.Name)
d.Set("admin_distance", res.AdminDistance)
d.Set("ip_address_prefix", res.IPAddressPrefix)
d.Set("next_hop_vnic_set", res.NextHopVnicSet)
d.Set("description", res.Description)
if err := setStringList(d, "tags", res.Tags); err != nil {
return err
}
return nil
}
func resourceOPCRouteUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Routes()
// Get Required attributes
name := d.Get("name").(string)
ipPrefix := d.Get("ip_address_prefix").(string)
nextHop := d.Get("next_hop_vnic_set").(string)
// Start populating input struct
input := &compute.UpdateRouteInput{
Name: name,
IPAddressPrefix: ipPrefix,
NextHopVnicSet: nextHop,
}
// Get Optional Attributes
desc, descOk := d.GetOk("description")
if descOk {
input.Description = desc.(string)
}
dist, distOk := d.GetOk("admin_distance")
if distOk {
input.AdminDistance = dist.(int)
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
// Create Route
info, err := client.UpdateRoute(input)
if err != nil {
return fmt.Errorf("Error creating route '%s': %v", name, err)
}
d.SetId(info.Name)
return resourceOPCRouteRead(d, meta)
}
func resourceOPCRouteDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).Routes()
name := d.Id()
input := &compute.DeleteRouteInput{
Name: name,
}
if err := client.DeleteRoute(input); err != nil {
return fmt.Errorf("Error deleting route '%s': %v", name, err)
}
return nil
}

View File

@ -0,0 +1,163 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCRoute_Basic(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_route.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckRouteDestroy,
Steps: []resource.TestStep{
{
Config: testAccOPCRouteConfig_Basic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckRouteExists,
resource.TestCheckResourceAttr(resName, "admin_distance", "1"),
resource.TestCheckResourceAttr(resName, "ip_address_prefix", "10.0.12.0/24"),
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-route-%d", rInt)),
),
},
{
Config: testAccOPCRouteConfig_BasicUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckRouteExists,
resource.TestCheckResourceAttr(resName, "admin_distance", "2"),
resource.TestCheckResourceAttr(resName, "ip_address_prefix", "10.0.14.0/24"),
),
},
},
})
}
func testAccOPCRouteConfig_Basic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-route-%d"
description = "testing-route"
ip_address_prefix = "10.1.14.0/24"
}
resource "opc_compute_instance" "foo" {
name = "test-route-%d"
label = "testing"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-set-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "foo" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth0"
}
resource "opc_compute_vnic_set" "test" {
name = "route-test-%d"
description = "route-testing-%d"
virtual_nics = ["${data.opc_compute_network_interface.foo.vnic}"]
}
resource "opc_compute_route" "test" {
name = "testing-route-%d"
description = "testing-desc-%d"
admin_distance = 1
ip_address_prefix = "10.0.12.0/24"
next_hop_vnic_set = "${opc_compute_vnic_set.test.name}"
}`, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}
func testAccOPCRouteConfig_BasicUpdate(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-route-%d"
description = "testing-route"
ip_address_prefix = "10.1.14.0/24"
}
resource "opc_compute_instance" "foo" {
name = "test-route-%d"
label = "testing"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-set-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "foo" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth0"
}
resource "opc_compute_vnic_set" "test" {
name = "route-test-%d"
description = "route-testing-%d"
virtual_nics = ["${data.opc_compute_network_interface.foo.vnic}"]
}
resource "opc_compute_route" "test" {
name = "testing-route-%d"
description = "testing-desc-%d"
admin_distance = 2
ip_address_prefix = "10.0.14.0/24"
next_hop_vnic_set = "${opc_compute_vnic_set.test.name}"
}`, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}
func testAccOPCCheckRouteExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).Routes()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_route" {
continue
}
input := compute.GetRouteInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetRoute(&input); err != nil {
return fmt.Errorf("Error retrieving state of Rule %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckRouteDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).Routes()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_route" {
continue
}
input := compute.GetRouteInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetRoute(&input); err == nil {
return fmt.Errorf("Rule %s still exists: %#v", input.Name, info)
}
}
return nil
}

View File

@ -0,0 +1,163 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSecRule() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecRuleCreate,
Read: resourceOPCSecRuleRead,
Update: resourceOPCSecRuleUpdate,
Delete: resourceOPCSecRuleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"source_list": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"destination_list": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"application": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"action": {
Type: schema.TypeString,
Required: true,
},
"disabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}
}
func resourceOPCSecRuleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecRules()
name := d.Get("name").(string)
sourceList := d.Get("source_list").(string)
destinationList := d.Get("destination_list").(string)
application := d.Get("application").(string)
action := d.Get("action").(string)
disabled := d.Get("disabled").(bool)
input := compute.CreateSecRuleInput{
Name: name,
Action: action,
SourceList: sourceList,
DestinationList: destinationList,
Disabled: disabled,
Application: application,
}
desc, descOk := d.GetOk("description")
if descOk {
input.Description = desc.(string)
}
info, err := client.CreateSecRule(&input)
if err != nil {
return fmt.Errorf("Error creating sec rule %s: %s", name, err)
}
d.SetId(info.Name)
return resourceOPCSecRuleRead(d, meta)
}
func resourceOPCSecRuleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecRules()
name := d.Id()
input := compute.GetSecRuleInput{
Name: name,
}
result, err := client.GetSecRule(&input)
if err != nil {
// Sec Rule does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading sec list %s: %s", name, err)
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("source_list", result.SourceList)
d.Set("destination_list", result.DestinationList)
d.Set("application", result.Application)
d.Set("action", result.Action)
d.Set("disabled", result.Disabled)
return nil
}
func resourceOPCSecRuleUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecRules()
name := d.Get("name").(string)
sourceList := d.Get("source_list").(string)
destinationList := d.Get("destination_list").(string)
application := d.Get("application").(string)
action := d.Get("action").(string)
disabled := d.Get("disabled").(bool)
input := compute.UpdateSecRuleInput{
Action: action,
Application: application,
DestinationList: destinationList,
Disabled: disabled,
Name: name,
SourceList: sourceList,
}
desc, descOk := d.GetOk("description")
if descOk {
input.Description = desc.(string)
}
_, err := client.UpdateSecRule(&input)
if err != nil {
return fmt.Errorf("Error updating sec rule %s: %s", name, err)
}
return resourceOPCSecRuleRead(d, meta)
}
func resourceOPCSecRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecRules()
name := d.Id()
input := compute.DeleteSecRuleInput{
Name: name,
}
if err := client.DeleteSecRule(&input); err != nil {
return fmt.Errorf("Error deleting sec rule %s: %s", name, err)
}
return nil
}

View File

@ -0,0 +1,138 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecRule_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecRuleBasic, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckSecRuleExists,
},
},
})
}
func TestAccOPCSecRule_Complete(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecRuleComplete, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecRuleDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckSecRuleExists,
},
},
})
}
func testAccCheckSecRuleExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecRules()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_sec_rule" {
continue
}
input := compute.GetSecRuleInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecRule(&input); err != nil {
return fmt.Errorf("Error retrieving state of Sec Rule %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckSecRuleDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecRules()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_sec_rule" {
continue
}
input := compute.GetSecRuleInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecRule(&input); err == nil {
return fmt.Errorf("Sec Rule %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccOPCSecRuleBasic = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-rule-list-%d"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
resource "opc_compute_security_application" "test" {
name = "acc-test-sec-rule-app-%d"
protocol = "tcp"
dport = "8080"
}
resource "opc_compute_security_ip_list" "test" {
name = "acc-test-sec-rule-ip-list-%d"
ip_entries = ["217.138.34.4"]
}
resource "opc_compute_sec_rule" "test" {
name = "acc-test-sec-rule-%d"
source_list = "seclist:${opc_compute_security_list.test.name}"
destination_list = "seciplist:${opc_compute_security_ip_list.test.name}"
action = "PERMIT"
application = "${opc_compute_security_application.test.name}"
}
`
var testAccOPCSecRuleComplete = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-rule-list-%d"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
resource "opc_compute_security_application" "test" {
name = "acc-test-sec-rule-app-%d"
protocol = "tcp"
dport = "8080"
}
resource "opc_compute_security_ip_list" "test" {
name = "acc-test-sec-rule-ip-list-%d"
ip_entries = ["217.138.34.4"]
}
resource "opc_compute_sec_rule" "test" {
name = "acc-test-sec-rule-%d"
source_list = "seclist:${opc_compute_security_list.test.name}"
destination_list = "seciplist:${opc_compute_security_ip_list.test.name}"
action = "PERMIT"
application = "${opc_compute_security_application.test.name}"
disabled = false
description = "This is a test description"
}
`

View File

@ -0,0 +1,140 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceOPCSecurityApplication() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityApplicationCreate,
Read: resourceOPCSecurityApplicationRead,
Delete: resourceOPCSecurityApplicationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"protocol": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateIPProtocol,
ForceNew: true,
},
"dport": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"icmptype": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(compute.Echo),
string(compute.Reply),
string(compute.TTL),
string(compute.TraceRoute),
string(compute.Unreachable),
}, true),
ForceNew: true,
},
"icmpcode": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(compute.Admin),
string(compute.Df),
string(compute.Host),
string(compute.Network),
string(compute.Port),
string(compute.Protocol),
}, true),
ForceNew: true,
},
},
}
}
func resourceOPCSecurityApplicationCreate(d *schema.ResourceData, meta interface{}) error {
name := d.Get("name").(string)
protocol := d.Get("protocol").(string)
dport := d.Get("dport").(string)
icmptype := d.Get("icmptype").(string)
icmpcode := d.Get("icmpcode").(string)
description := d.Get("description").(string)
client := meta.(*compute.Client).SecurityApplications()
input := compute.CreateSecurityApplicationInput{
Name: name,
Description: description,
Protocol: compute.SecurityApplicationProtocol(protocol),
DPort: dport,
ICMPCode: compute.SecurityApplicationICMPCode(icmpcode),
ICMPType: compute.SecurityApplicationICMPType(icmptype),
}
info, err := client.CreateSecurityApplication(&input)
if err != nil {
return fmt.Errorf("Error creating security application %s: %s", name, err)
}
d.SetId(info.Name)
return resourceOPCSecurityApplicationRead(d, meta)
}
func resourceOPCSecurityApplicationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityApplications()
name := d.Id()
input := compute.GetSecurityApplicationInput{
Name: name,
}
result, err := client.GetSecurityApplication(&input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading security application %s: %s", name, err)
}
d.Set("name", result.Name)
d.Set("protocol", result.Protocol)
d.Set("dport", result.DPort)
d.Set("icmptype", result.ICMPType)
d.Set("icmpcode", result.ICMPCode)
d.Set("description", result.Description)
return nil
}
func resourceOPCSecurityApplicationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityApplications()
name := d.Id()
input := compute.DeleteSecurityApplicationInput{
Name: name,
}
if err := client.DeleteSecurityApplication(&input); err != nil {
return fmt.Errorf("Error deleting security application '%s': %s", name, err)
}
return nil
}

View File

@ -0,0 +1,101 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityApplication_ICMP(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityApplicationICMP, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityApplicationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccOPCCheckSecurityApplicationExists,
},
},
})
}
func TestAccOPCSecurityApplication_TCP(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityApplicationTCP, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityApplicationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccOPCCheckSecurityApplicationExists,
},
},
})
}
func testAccOPCCheckSecurityApplicationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityApplications()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_application" {
continue
}
input := compute.GetSecurityApplicationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityApplication(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security Application %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckSecurityApplicationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityApplications()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_application" {
continue
}
input := compute.GetSecurityApplicationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityApplication(&input); err == nil {
return fmt.Errorf("Security Application %s still exists: %#v", input.Name, info)
}
}
return nil
}
const testAccOPCSecurityApplicationTCP = `
resource "opc_compute_security_application" "test" {
name = "acc-security-application-tcp-%d"
protocol = "tcp"
dport = "8080"
description = "Terraform Acceptance Test"
}
`
const testAccOPCSecurityApplicationICMP = `
resource "opc_compute_security_application" "test" {
name = "acc-security-application-tcp-%d"
protocol = "icmp"
icmptype = "echo"
description = "Terraform Acceptance Test"
}
`

View File

@ -0,0 +1,101 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSecurityAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityAssociationCreate,
Read: resourceOPCSecurityAssociationRead,
Delete: resourceOPCSecurityAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"vcable": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"seclist": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceOPCSecurityAssociationCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityAssociations()
name := d.Get("name").(string)
vcable := d.Get("vcable").(string)
seclist := d.Get("seclist").(string)
input := compute.CreateSecurityAssociationInput{
Name: name,
SecList: seclist,
VCable: vcable,
}
info, err := client.CreateSecurityAssociation(&input)
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)
return resourceOPCSecurityAssociationRead(d, meta)
}
func resourceOPCSecurityAssociationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityAssociations()
name := d.Id()
input := compute.GetSecurityAssociationInput{
Name: name,
}
result, err := client.GetSecurityAssociation(&input)
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)
}
d.Set("name", result.Name)
d.Set("seclist", result.SecList)
d.Set("vcable", result.VCable)
return nil
}
func resourceOPCSecurityAssociationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityAssociations()
name := d.Id()
input := compute.DeleteSecurityAssociationInput{
Name: name,
}
if err := client.DeleteSecurityAssociation(&input); err != nil {
return fmt.Errorf("Error deleting Security Association '%s': %v", name, err)
}
return nil
}

View File

@ -0,0 +1,128 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityAssociation_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccSecurityAssociationBasic, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSecurityAssociationExists,
),
},
},
})
}
func TestAccOPCSecurityAssociation_Complete(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccSecurityAssociationComplete, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSecurityAssociationDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSecurityAssociationExists,
),
},
},
})
}
func testAccOPCCheckSecurityAssociationExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_association" {
continue
}
input := compute.GetSecurityAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityAssociation(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security Association %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckSecurityAssociationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityAssociations()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_association" {
continue
}
input := compute.GetSecurityAssociationInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityAssociation(&input); err == nil {
return fmt.Errorf("Security Association %s still exists: %#v", input.Name, info)
}
}
return nil
}
var testAccSecurityAssociationBasic = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-ass-sec-list-%d"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
resource "opc_compute_instance" "test" {
name = "acc-test-sec-ass-instance-%d"
label = "Security Associations Test Instance"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
}
resource "opc_compute_security_association" "test" {
vcable = "${opc_compute_instance.test.vcable}"
seclist = "${opc_compute_security_list.test.name}"
}
`
var testAccSecurityAssociationComplete = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-ass-sec-list-%d"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
resource "opc_compute_instance" "test" {
name = "acc-test-sec-ass-instance-%d"
label = "Security Associations Test Instance"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
}
resource "opc_compute_security_association" "test" {
name = "acc-test-sec-ass-%d"
vcable = "${opc_compute_instance.test.vcable}"
seclist = "${opc_compute_security_list.test.name}"
}
`

View File

@ -0,0 +1,135 @@
package opc
import (
"fmt"
"log"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSecurityIPList() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityIPListCreate,
Read: resourceOPCSecurityIPListRead,
Update: resourceOPCSecurityIPListUpdate,
Delete: resourceOPCSecurityIPListDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ip_entries": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"description": {
Type: schema.TypeString,
Optional: true,
},
},
}
}
func resourceOPCSecurityIPListCreate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).SecurityIPLists()
ipEntries := d.Get("ip_entries").([]interface{})
ipEntryStrings := []string{}
for _, entry := range ipEntries {
ipEntryStrings = append(ipEntryStrings, entry.(string))
}
input := compute.CreateSecurityIPListInput{
Name: d.Get("name").(string),
SecIPEntries: ipEntryStrings,
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
log.Printf("[DEBUG] Creating security IP list with %+v", input)
info, err := client.CreateSecurityIPList(&input)
if err != nil {
return fmt.Errorf("Error creating security IP list %s: %s", input.Name, err)
}
d.SetId(info.Name)
return resourceOPCSecurityIPListRead(d, meta)
}
func resourceOPCSecurityIPListRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).SecurityIPLists()
name := d.Id()
log.Printf("[DEBUG] Reading state of security IP list %s", name)
input := compute.GetSecurityIPListInput{
Name: name,
}
result, err := client.GetSecurityIPList(&input)
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)
d.Set("name", result.Name)
d.Set("ip_entries", result.SecIPEntries)
d.Set("description", result.Description)
return nil
}
func resourceOPCSecurityIPListUpdate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).SecurityIPLists()
ipEntries := d.Get("ip_entries").([]interface{})
ipEntryStrings := []string{}
for _, entry := range ipEntries {
ipEntryStrings = append(ipEntryStrings, entry.(string))
}
input := compute.UpdateSecurityIPListInput{
Name: d.Get("name").(string),
SecIPEntries: ipEntryStrings,
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
log.Printf("[DEBUG] Updating security IP list with %+v", input)
info, err := client.UpdateSecurityIPList(&input)
if err != nil {
return fmt.Errorf("Error updating security IP list %s: %s", input.Name, err)
}
d.SetId(info.Name)
return resourceOPCSecurityIPListRead(d, meta)
}
func resourceOPCSecurityIPListDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Resource state: %#v", d.State())
client := meta.(*compute.Client).SecurityIPLists()
name := d.Id()
log.Printf("[DEBUG] Deleting security IP list %s", name)
input := compute.DeleteSecurityIPListInput{
Name: name,
}
if err := client.DeleteSecurityIPList(&input); err != nil {
return fmt.Errorf("Error deleting security IP list %s: %s", name, err)
}
return nil
}

View File

@ -0,0 +1,117 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityIPList_Basic(t *testing.T) {
listResourceName := "opc_compute_security_ip_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityIPListBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityIPListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityIPListExists,
resource.TestCheckResourceAttr(listResourceName, "ip_entries.0", "192.168.0.1"),
resource.TestCheckResourceAttr(listResourceName, "ip_entries.1", "192.168.0.2"),
),
},
},
})
}
func TestAccOPCSecurityIPList_Updated(t *testing.T) {
listResourceName := "opc_compute_security_ip_list.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityIPListBasic, ri)
config2 := fmt.Sprintf(testAccOPCSecurityIPListUpdated, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityIPListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityIPListExists,
resource.TestCheckResourceAttr(listResourceName, "description", "Terraform Acceptance Test"),
),
},
{
Config: config2,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityIPListExists,
resource.TestCheckResourceAttr(listResourceName, "description", ""),
resource.TestCheckResourceAttr(listResourceName, "ip_entries.0", "192.168.0.1"),
resource.TestCheckResourceAttr(listResourceName, "ip_entries.1", "192.168.0.3"),
),
},
},
})
}
func testAccCheckSecurityIPListExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityIPLists()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_ip_list" {
continue
}
input := compute.GetSecurityIPListInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityIPList(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security IP List %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckSecurityIPListDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityIPLists()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_ip_list" {
continue
}
input := compute.GetSecurityIPListInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityIPList(&input); err == nil {
return fmt.Errorf("Security IP List %s still exists: %#v", input.Name, info)
}
}
return nil
}
const testAccOPCSecurityIPListBasic = `
resource "opc_compute_security_ip_list" "test" {
name = "acc-security-application-tcp-%d"
ip_entries = ["192.168.0.1", "192.168.0.2"]
description = "Terraform Acceptance Test"
}
`
const testAccOPCSecurityIPListUpdated = `
resource "opc_compute_security_ip_list" "test" {
name = "acc-security-application-tcp-%d"
ip_entries = ["192.168.0.1", "192.168.0.3"]
}
`

View File

@ -0,0 +1,141 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceOPCSecurityList() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityListCreate,
Read: resourceOPCSecurityListRead,
Update: resourceOPCSecurityListUpdate,
Delete: resourceOPCSecurityListDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"policy": {
Type: schema.TypeString,
Optional: true,
Default: "deny",
ValidateFunc: validation.StringInSlice([]string{
string(compute.SecurityListPolicyDeny),
string(compute.SecurityListPolicyPermit),
string(compute.SecurityListPolicyReject),
}, true),
},
"outbound_cidr_policy": {
Type: schema.TypeString,
Optional: true,
Default: "permit",
ValidateFunc: validation.StringInSlice([]string{
string(compute.SecurityListPolicyDeny),
string(compute.SecurityListPolicyPermit),
string(compute.SecurityListPolicyReject),
}, true),
},
},
}
}
func resourceOPCSecurityListCreate(d *schema.ResourceData, meta interface{}) error {
name := d.Get("name").(string)
description := d.Get("description").(string)
policy := d.Get("policy").(string)
outboundCIDRPolicy := d.Get("outbound_cidr_policy").(string)
client := meta.(*compute.Client).SecurityLists()
input := compute.CreateSecurityListInput{
Name: name,
Description: description,
Policy: compute.SecurityListPolicy(policy),
OutboundCIDRPolicy: compute.SecurityListPolicy(outboundCIDRPolicy),
}
info, err := client.CreateSecurityList(&input)
if err != nil {
return fmt.Errorf("Error creating security list %s: %s", name, err)
}
d.SetId(info.Name)
return resourceOPCSecurityListRead(d, meta)
}
func resourceOPCSecurityListUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityLists()
name := d.Get("name").(string)
description := d.Get("description").(string)
policy := d.Get("policy").(string)
outboundCIDRPolicy := d.Get("outbound_cidr_policy").(string)
input := compute.UpdateSecurityListInput{
Name: name,
Description: description,
Policy: compute.SecurityListPolicy(policy),
OutboundCIDRPolicy: compute.SecurityListPolicy(outboundCIDRPolicy),
}
_, err := client.UpdateSecurityList(&input)
if err != nil {
return fmt.Errorf("Error updating security list %s: %s", name, err)
}
return resourceOPCSecurityListRead(d, meta)
}
func resourceOPCSecurityListRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityLists()
name := d.Id()
input := compute.GetSecurityListInput{
Name: name,
}
result, err := client.GetSecurityList(&input)
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)
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("policy", string(result.Policy))
d.Set("outbound_cidr_policy", string(result.OutboundCIDRPolicy))
return nil
}
func resourceOPCSecurityListDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityLists()
name := d.Id()
input := compute.DeleteSecurityListInput{
Name: name,
}
if err := client.DeleteSecurityList(&input); err != nil {
return fmt.Errorf("Error deleting security list %s: %s", name, err)
}
return nil
}

View File

@ -0,0 +1,100 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityList_basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityListBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckSecurityListExists,
},
},
})
}
func TestAccOPCSecurityList_complete(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityListComplete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityListDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: testAccCheckSecurityListExists,
},
},
})
}
func testAccCheckSecurityListExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityLists()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_list" {
continue
}
input := compute.GetSecurityListInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityList(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security List %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckSecurityListDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityLists()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_list" {
continue
}
input := compute.GetSecurityListInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityList(&input); err == nil {
return fmt.Errorf("Security List %s still exists: %#v", input.Name, info)
}
}
return nil
}
const testAccOPCSecurityListBasic = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-list-%d"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
`
const testAccOPCSecurityListComplete = `
resource "opc_compute_security_list" "test" {
name = "acc-test-sec-list-%d"
description = "Acceptance Test Security List Complete"
policy = "PERMIT"
outbound_cidr_policy = "DENY"
}
`

View File

@ -0,0 +1,160 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSecurityProtocol() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityProtocolCreate,
Read: resourceOPCSecurityProtocolRead,
Update: resourceOPCSecurityProtocolUpdate,
Delete: resourceOPCSecurityProtocolDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"dst_ports": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"ip_protocol": {
Type: schema.TypeString,
Optional: true,
Default: string(compute.All),
ValidateFunc: validateIPProtocol,
},
"src_ports": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"tags": tagsForceNewSchema(),
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCSecurityProtocolCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityProtocols()
input := compute.CreateSecurityProtocolInput{
Name: d.Get("name").(string),
IPProtocol: d.Get("ip_protocol").(string),
}
dstPorts := getStringList(d, "dst_ports")
if len(dstPorts) != 0 {
input.DstPortSet = dstPorts
}
srcPorts := getStringList(d, "src_ports")
if len(srcPorts) != 0 {
input.SrcPortSet = srcPorts
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateSecurityProtocol(&input)
if err != nil {
return fmt.Errorf("Error creating Security Protocol: %s", err)
}
d.SetId(info.Name)
return resourceOPCSecurityProtocolRead(d, meta)
}
func resourceOPCSecurityProtocolRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityProtocols()
getInput := compute.GetSecurityProtocolInput{
Name: d.Id(),
}
result, err := client.GetSecurityProtocol(&getInput)
if err != nil {
// Security Protocol does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading security protocol %s: %s", d.Id(), err)
}
d.Set("name", result.Name)
d.Set("ip_protocol", result.IPProtocol)
d.Set("description", result.Description)
if err := setStringList(d, "dst_ports", result.DstPortSet); err != nil {
return err
}
if err := setStringList(d, "src_ports", result.SrcPortSet); err != nil {
return err
}
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCSecurityProtocolUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityProtocols()
input := compute.UpdateSecurityProtocolInput{
Name: d.Get("name").(string),
IPProtocol: d.Get("ip_protocol").(string),
}
dstPorts := getStringList(d, "dst_ports")
if len(dstPorts) != 0 {
input.DstPortSet = dstPorts
}
srcPorts := getStringList(d, "src_ports")
if len(srcPorts) != 0 {
input.SrcPortSet = srcPorts
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateSecurityProtocol(&input)
if err != nil {
return fmt.Errorf("Error updating Security Protocol: %s", err)
}
d.SetId(info.Name)
return resourceOPCSecurityProtocolRead(d, meta)
}
func resourceOPCSecurityProtocolDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityProtocols()
name := d.Id()
input := compute.DeleteSecurityProtocolInput{
Name: name,
}
if err := client.DeleteSecurityProtocol(&input); err != nil {
return fmt.Errorf("Error deleting Security Protocol: %s", err)
}
return nil
}

View File

@ -0,0 +1,153 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityProtocol_Basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityProtocolBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityProtocolDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityProtocolExists,
),
},
},
})
}
func TestAccOPCSecurityProtocol_Complete(t *testing.T) {
protocolResourceName := "opc_compute_security_protocol.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityProtocolComplete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityProtocolDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityProtocolExists,
resource.TestCheckResourceAttr(protocolResourceName, "description", "Terraform Acceptance Test"),
resource.TestCheckResourceAttr(protocolResourceName, "dst_ports.0", "2025-2030"),
resource.TestCheckResourceAttr(protocolResourceName, "src_ports.0", "3025-3030"),
resource.TestCheckResourceAttr(protocolResourceName, "ip_protocol", "tcp"),
),
},
},
})
}
func TestAccOPCSecurityProtocol_Update(t *testing.T) {
protocolResourceName := "opc_compute_security_protocol.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSecurityProtocolComplete, ri)
config2 := fmt.Sprintf(testAccOPCSecurityProtocolUpdated, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityProtocolDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityProtocolExists,
resource.TestCheckResourceAttr(protocolResourceName, "description", "Terraform Acceptance Test"),
resource.TestCheckResourceAttr(protocolResourceName, "dst_ports.0", "2025-2030"),
resource.TestCheckResourceAttr(protocolResourceName, "src_ports.0", "3025-3030"),
resource.TestCheckResourceAttr(protocolResourceName, "ip_protocol", "tcp"),
),
},
{
Config: config2,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityProtocolExists,
resource.TestCheckResourceAttr(protocolResourceName, "description", ""),
resource.TestCheckResourceAttr(protocolResourceName, "dst_ports.1", "2040-2050"),
resource.TestCheckResourceAttr(protocolResourceName, "src_ports.1", "3040-3050"),
resource.TestCheckResourceAttr(protocolResourceName, "ip_protocol", "udp"),
),
},
},
})
}
func testAccCheckSecurityProtocolExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityProtocols()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_protocol" {
continue
}
input := compute.GetSecurityProtocolInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityProtocol(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security Protocol %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckSecurityProtocolDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityProtocols()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_protocol" {
continue
}
input := compute.GetSecurityProtocolInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityProtocol(&input); err == nil {
return fmt.Errorf("Security Protocol %s still exists: %#v", input.Name, info)
}
}
return nil
}
const testAccOPCSecurityProtocolBasic = `
resource "opc_compute_security_protocol" "test" {
name = "acc-security-protocol-%d"
description = "Terraform Acceptance Test"
}
`
const testAccOPCSecurityProtocolComplete = `
resource "opc_compute_security_protocol" "test" {
name = "acc-security-protocol-%d"
description = "Terraform Acceptance Test"
dst_ports = ["2025-2030"]
src_ports = ["3025-3030"]
ip_protocol = "tcp"
}
`
const testAccOPCSecurityProtocolUpdated = `
resource "opc_compute_security_protocol" "test" {
name = "acc-security-protocol-%d"
dst_ports = ["2025-2030", "2040-2050"]
src_ports = ["3025-3030", "3040-3050"]
ip_protocol = "udp"
}
`

View File

@ -0,0 +1,231 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSecurityRule() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSecurityRuleCreate,
Read: resourceOPCSecurityRuleRead,
Update: resourceOPCSecurityRuleUpdate,
Delete: resourceOPCSecurityRuleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"flow_direction": {
Type: schema.TypeString,
Required: true,
},
"acl": {
Type: schema.TypeString,
Optional: true,
},
"dst_ip_address_prefixes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"src_ip_address_prefixes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"security_protocols": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"dst_vnic_set": {
Type: schema.TypeString,
Optional: true,
},
"src_vnic_set": {
Type: schema.TypeString,
Optional: true,
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"tags": tagsOptionalSchema(),
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCSecurityRuleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityRules()
input := compute.CreateSecurityRuleInput{
Name: d.Get("name").(string),
FlowDirection: d.Get("flow_direction").(string),
Enabled: d.Get("enabled").(bool),
}
if acl, ok := d.GetOk("acl"); ok {
input.ACL = acl.(string)
}
if srcVNicSet, ok := d.GetOk("src_vnic_set"); ok {
input.SrcVnicSet = srcVNicSet.(string)
}
if dstVNicSet, ok := d.GetOk("dst_vnic_set"); ok {
input.DstVnicSet = dstVNicSet.(string)
}
securityProtocols := getStringList(d, "security_protocols")
if len(securityProtocols) != 0 {
input.SecProtocols = securityProtocols
}
srcIPAdressPrefixes := getStringList(d, "src_ip_address_prefixes")
if len(srcIPAdressPrefixes) != 0 {
input.SrcIpAddressPrefixSets = srcIPAdressPrefixes
}
dstIPAdressPrefixes := getStringList(d, "dst_ip_address_prefixes")
if len(dstIPAdressPrefixes) != 0 {
input.DstIpAddressPrefixSets = dstIPAdressPrefixes
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.CreateSecurityRule(&input)
if err != nil {
return fmt.Errorf("Error creating Security Rule: %s", err)
}
d.SetId(info.Name)
return resourceOPCSecurityRuleRead(d, meta)
}
func resourceOPCSecurityRuleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityRules()
getInput := compute.GetSecurityRuleInput{
Name: d.Id(),
}
result, err := client.GetSecurityRule(&getInput)
if err != nil {
// SecurityRule does not exist
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading security rule %s: %s", d.Id(), err)
}
d.Set("name", result.Name)
d.Set("flow_direction", result.FlowDirection)
d.Set("enabled", result.Enabled)
d.Set("acl", result.ACL)
d.Set("src_vnic_set", result.SrcVnicSet)
d.Set("dst_vnic_set", result.DstVnicSet)
d.Set("description", result.Description)
d.Set("uri", result.Uri)
if err := setStringList(d, "security_protocols", result.SecProtocols); err != nil {
return err
}
if err := setStringList(d, "dst_ip_address_prefixes", result.DstIpAddressPrefixSets); err != nil {
return err
}
if err := setStringList(d, "src_ip_address_prefixes", result.SrcIpAddressPrefixSets); err != nil {
return err
}
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCSecurityRuleUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityRules()
input := compute.UpdateSecurityRuleInput{
Name: d.Get("name").(string),
FlowDirection: d.Get("flow_direction").(string),
Enabled: d.Get("enabled").(bool),
}
if acl, ok := d.GetOk("acl"); ok {
input.ACL = acl.(string)
}
if srcVNicSet, ok := d.GetOk("src_vnic_set"); ok {
input.SrcVnicSet = srcVNicSet.(string)
}
if dstVNicSet, ok := d.GetOk("dst_vnic_set"); ok {
input.DstVnicSet = dstVNicSet.(string)
}
securityProtocols := getStringList(d, "security_protocols")
if len(securityProtocols) != 0 {
input.SecProtocols = securityProtocols
}
srcIPAdressPrefixes := getStringList(d, "src_ip_address_prefixes")
if len(srcIPAdressPrefixes) != 0 {
input.SrcIpAddressPrefixSets = srcIPAdressPrefixes
}
dstIPAdressPrefixes := getStringList(d, "dst_ip_address_prefixes")
if len(dstIPAdressPrefixes) != 0 {
input.DstIpAddressPrefixSets = dstIPAdressPrefixes
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
if description, ok := d.GetOk("description"); ok {
input.Description = description.(string)
}
info, err := client.UpdateSecurityRule(&input)
if err != nil {
return fmt.Errorf("Error updating Security Rule: %s", err)
}
d.SetId(info.Name)
return resourceOPCSecurityRuleRead(d, meta)
}
func resourceOPCSecurityRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SecurityRules()
name := d.Id()
input := compute.DeleteSecurityRuleInput{
Name: name,
}
if err := client.DeleteSecurityRule(&input); err != nil {
return fmt.Errorf("Error deleting Security Rule: %s", err)
}
return nil
}

View File

@ -0,0 +1,159 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSecurityRule_Basic(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_security_rule.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccOPCSecurityRuleConfig_Basic(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityRuleExists,
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-security-rule-%d", rInt)),
),
},
{
Config: testAccOPCSecurityRuleConfig_BasicUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityRuleExists,
resource.TestCheckResourceAttr(resName, "enabled", "false"),
),
},
},
})
}
func TestAccOPCSecurityRule_Full(t *testing.T) {
rInt := acctest.RandInt()
resName := "opc_compute_security_rule.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccOPCSecurityRuleConfig_Full(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityRuleExists,
resource.TestCheckResourceAttr(resName, "name", fmt.Sprintf("testing-security-rule-%d", rInt)),
resource.TestCheckResourceAttr(resName, "acl", fmt.Sprintf("test-security-rule-%d", rInt)),
resource.TestCheckResourceAttr(resName, "src_vnic_set", fmt.Sprintf("test-security-rule-src-%d", rInt)),
resource.TestCheckResourceAttr(resName, "dst_vnic_set", fmt.Sprintf("test-security-rule-dst-%d", rInt)),
resource.TestCheckResourceAttr(resName, "dst_ip_address_prefixes.0", fmt.Sprintf("test-security-rule-dst-%d", rInt)),
resource.TestCheckResourceAttr(resName, "src_ip_address_prefixes.0", fmt.Sprintf("test-security-rule-src-%d", rInt)),
resource.TestCheckResourceAttr(resName, "security_protocols.0", fmt.Sprintf("test-security-rule-%d", rInt)),
),
},
},
})
}
func testAccCheckSecurityRuleExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityRules()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_sec_rule" {
continue
}
input := compute.GetSecurityRuleInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSecurityRule(&input); err != nil {
return fmt.Errorf("Error retrieving state of Security Rule %s: %s", input.Name, err)
}
}
return nil
}
func testAccCheckSecurityRuleDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SecurityRules()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_security_rule" {
continue
}
input := compute.GetSecurityRuleInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSecurityRule(&input); err == nil {
return fmt.Errorf("Security Rule %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccOPCSecurityRuleConfig_Basic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_security_rule" "test" {
name = "testing-security-rule-%d"
description = "testing-desc-%d"
flow_direction = "ingress"
}`, rInt, rInt)
}
func testAccOPCSecurityRuleConfig_BasicUpdate(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_security_rule" "test" {
name = "testing-security-rule-%d"
description = "testing-desc-%d"
flow_direction = "egress"
enabled = false
}`, rInt, rInt)
}
func testAccOPCSecurityRuleConfig_Full(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_acl" "test" {
name = "test-security-rule-%d"
}
resource "opc_compute_vnic_set" "src" {
name = "test-security-rule-src-%d"
}
resource "opc_compute_vnic_set" "dst" {
name = "test-security-rule-dst-%d"
}
resource "opc_compute_security_protocol" "test" {
name = "test-security-rule-%d"
}
resource "opc_compute_ip_address_prefix_set" "src" {
name = "test-security-rule-src-%d"
}
resource "opc_compute_ip_address_prefix_set" "dst" {
name = "test-security-rule-dst-%d"
}
resource "opc_compute_security_rule" "test" {
name = "testing-security-rule-%d"
description = "testing-desc-%d"
flow_direction = "ingress"
acl = "${opc_compute_acl.test.name}"
src_vnic_set = "${opc_compute_vnic_set.src.name}"
dst_vnic_set = "${opc_compute_vnic_set.dst.name}"
dst_ip_address_prefixes = ["${opc_compute_ip_address_prefix_set.dst.name}"]
src_ip_address_prefixes = ["${opc_compute_ip_address_prefix_set.src.name}"]
security_protocols = ["${opc_compute_security_protocol.test.name}"]
}`, rInt, rInt, rInt, rInt, rInt, rInt, rInt, rInt)
}

View File

@ -0,0 +1,118 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCSSHKey() *schema.Resource {
return &schema.Resource{
Create: resourceOPCSSHKeyCreate,
Read: resourceOPCSSHKeyRead,
Update: resourceOPCSSHKeyUpdate,
Delete: resourceOPCSSHKeyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"key": {
Type: schema.TypeString,
Required: true,
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
},
}
}
func resourceOPCSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SSHKeys()
name := d.Get("name").(string)
key := d.Get("key").(string)
enabled := d.Get("enabled").(bool)
input := compute.CreateSSHKeyInput{
Name: name,
Key: key,
Enabled: enabled,
}
info, err := client.CreateSSHKey(&input)
if err != nil {
return fmt.Errorf("Error creating ssh key %s: %s", name, err)
}
d.SetId(info.Name)
return resourceOPCSSHKeyRead(d, meta)
}
func resourceOPCSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SSHKeys()
name := d.Get("name").(string)
key := d.Get("key").(string)
enabled := d.Get("enabled").(bool)
input := compute.UpdateSSHKeyInput{
Name: name,
Key: key,
Enabled: enabled,
}
_, err := client.UpdateSSHKey(&input)
if err != nil {
return fmt.Errorf("Error updating ssh key %s: %s", name, err)
}
return resourceOPCSSHKeyRead(d, meta)
}
func resourceOPCSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SSHKeys()
name := d.Id()
input := compute.GetSSHKeyInput{
Name: name,
}
result, err := client.GetSSHKey(&input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading ssh key %s: %s", name, err)
}
d.Set("name", result.Name)
d.Set("key", result.Key)
d.Set("enabled", result.Enabled)
return nil
}
func resourceOPCSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).SSHKeys()
name := d.Id()
input := compute.DeleteSSHKeyInput{
Name: name,
}
if err := client.DeleteSSHKey(&input); err != nil {
return fmt.Errorf("Error deleting ssh key %s: %s", name, err)
}
return nil
}

View File

@ -0,0 +1,152 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCSSHKey_basic(t *testing.T) {
ruleResourceName := "opc_compute_ssh_key.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSSHKeyBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSSHKeyDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSSHKeyExists,
resource.TestCheckResourceAttr(ruleResourceName, "key", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Wa2OClh4LDCpR4A1x251PfzeUHvA3uo3Z4joYKIlQXP6242588bq6eh79ihm+HZAuxNoIkkS4OMIelUtiHcYSMYK7niXpato3cUdQHXjwchZjc3wwcXC/hAWK2QJkO7yLgCuYMTqyz2saZ/9zW12QS24rJH1DKFDbq4V40+HF7PQoq6G40Dp0X+slZri223pHJiqHKlyhUZuvMar7QnLZlZ7jenPyqVSpY7IC5KPj6geQSD2tSnVKjRo4TWVkIexSo6iHEu5vzcjVYGBw9RVGhmOd8pCcbB85M01MJFdbqLMjUHREE7/t767hmem3YdSPhMvnbBNPb7VSB+8ZQKn"),
),
},
},
})
}
func TestAccOPCSSHKey_update(t *testing.T) {
ruleResourceName := "opc_compute_ssh_key.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSSHKeyBasic, ri)
updatedConfig := fmt.Sprintf(testAccOPCSSHKeyUpdated, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSSHKeyDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSSHKeyExists,
resource.TestCheckResourceAttr(ruleResourceName, "key", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Wa2OClh4LDCpR4A1x251PfzeUHvA3uo3Z4joYKIlQXP6242588bq6eh79ihm+HZAuxNoIkkS4OMIelUtiHcYSMYK7niXpato3cUdQHXjwchZjc3wwcXC/hAWK2QJkO7yLgCuYMTqyz2saZ/9zW12QS24rJH1DKFDbq4V40+HF7PQoq6G40Dp0X+slZri223pHJiqHKlyhUZuvMar7QnLZlZ7jenPyqVSpY7IC5KPj6geQSD2tSnVKjRo4TWVkIexSo6iHEu5vzcjVYGBw9RVGhmOd8pCcbB85M01MJFdbqLMjUHREE7/t767hmem3YdSPhMvnbBNPb7VSB+8ZQKn"),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSSHKeyExists,
resource.TestCheckResourceAttr(ruleResourceName, "key", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDeXD/4cetIxK3a/mNbE8F0oYFOicK07Am6YyS0tV4Etak29fB2FoRwGAMETN0w7kKa8nKyvjZBH2mTkdAELoSbB70yZLNSufK7GMyLQXRG8c51xFDhTjLXZ92zSN6ZZBrnc7Z7iXCHsfAyXcrTmv9jgm3nE0QF1/AJgHXNa6GqzsyjilKkRjQBhUTqkTQylyVytPJHgM5W/v2vStfFK5wY9h9oDiHJiNACPOxE8v9A+u9MnKaq+E6AuarA0VQJbPWqVzoHWMUXL0ck+WYfZyX17VPB6c18h4Wn27lNxCEE7jaMLIVbMpAW5ICW1UVnrT6/ZoSTseJjEBlukPlZVQu7"),
),
},
},
})
}
func TestAccOPCSSHKey_disable(t *testing.T) {
ruleResourceName := "opc_compute_ssh_key.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccOPCSSHKeyBasic, ri)
updatedConfig := fmt.Sprintf(testAccOPCSSHKeyDisabled, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckSSHKeyDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSSHKeyExists,
resource.TestCheckResourceAttr(ruleResourceName, "enabled", "true"),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckSSHKeyExists,
resource.TestCheckResourceAttr(ruleResourceName, "enabled", "false"),
),
},
},
})
}
func testAccOPCCheckSSHKeyExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SSHKeys()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ssh_key" {
continue
}
input := compute.GetSSHKeyInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetSSHKey(&input); err != nil {
return fmt.Errorf("Error retrieving state of SSH Key %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckSSHKeyDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).SSHKeys()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_ssh_key" {
continue
}
input := compute.GetSSHKeyInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetSSHKey(&input); err == nil {
return fmt.Errorf("SSH Key %s still exists: %#v", input.Name, info)
}
}
return nil
}
const testAccOPCSSHKeyBasic = `
resource "opc_compute_ssh_key" "test" {
name = "acc-ssh-key-%d"
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Wa2OClh4LDCpR4A1x251PfzeUHvA3uo3Z4joYKIlQXP6242588bq6eh79ihm+HZAuxNoIkkS4OMIelUtiHcYSMYK7niXpato3cUdQHXjwchZjc3wwcXC/hAWK2QJkO7yLgCuYMTqyz2saZ/9zW12QS24rJH1DKFDbq4V40+HF7PQoq6G40Dp0X+slZri223pHJiqHKlyhUZuvMar7QnLZlZ7jenPyqVSpY7IC5KPj6geQSD2tSnVKjRo4TWVkIexSo6iHEu5vzcjVYGBw9RVGhmOd8pCcbB85M01MJFdbqLMjUHREE7/t767hmem3YdSPhMvnbBNPb7VSB+8ZQKn"
enabled = true
}
`
const testAccOPCSSHKeyUpdated = `
resource "opc_compute_ssh_key" "test" {
name = "acc-ssh-key-%d"
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDeXD/4cetIxK3a/mNbE8F0oYFOicK07Am6YyS0tV4Etak29fB2FoRwGAMETN0w7kKa8nKyvjZBH2mTkdAELoSbB70yZLNSufK7GMyLQXRG8c51xFDhTjLXZ92zSN6ZZBrnc7Z7iXCHsfAyXcrTmv9jgm3nE0QF1/AJgHXNa6GqzsyjilKkRjQBhUTqkTQylyVytPJHgM5W/v2vStfFK5wY9h9oDiHJiNACPOxE8v9A+u9MnKaq+E6AuarA0VQJbPWqVzoHWMUXL0ck+WYfZyX17VPB6c18h4Wn27lNxCEE7jaMLIVbMpAW5ICW1UVnrT6/ZoSTseJjEBlukPlZVQu7"
enabled = true
}
`
const testAccOPCSSHKeyDisabled = `
resource "opc_compute_ssh_key" "test" {
name = "acc-ssh-key-%d"
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Wa2OClh4LDCpR4A1x251PfzeUHvA3uo3Z4joYKIlQXP6242588bq6eh79ihm+HZAuxNoIkkS4OMIelUtiHcYSMYK7niXpato3cUdQHXjwchZjc3wwcXC/hAWK2QJkO7yLgCuYMTqyz2saZ/9zW12QS24rJH1DKFDbq4V40+HF7PQoq6G40Dp0X+slZri223pHJiqHKlyhUZuvMar7QnLZlZ7jenPyqVSpY7IC5KPj6geQSD2tSnVKjRo4TWVkIexSo6iHEu5vzcjVYGBw9RVGhmOd8pCcbB85M01MJFdbqLMjUHREE7/t767hmem3YdSPhMvnbBNPb7VSB+8ZQKn"
enabled = false
}
`

View File

@ -0,0 +1,285 @@
package opc
import (
"fmt"
"strconv"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceOPCStorageVolume() *schema.Resource {
return &schema.Resource{
Create: resourceOPCStorageVolumeCreate,
Read: resourceOPCStorageVolumeRead,
Update: resourceOPCStorageVolumeUpdate,
Delete: resourceOPCStorageVolumeDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"size": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 2048),
},
"storage_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: compute.StorageVolumeKindDefault,
ValidateFunc: validation.StringInSlice([]string{
string(compute.StorageVolumeKindDefault),
string(compute.StorageVolumeKindLatency),
}, true),
},
"snapshot": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"snapshot_account": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"image_list": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"image_list_entry": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Default: -1,
},
"tags": tagsOptionalSchema(),
// Computed fields
"hypervisor": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"machine_image": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"managed": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"platform": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"readonly": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"status": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"storage_pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"uri": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceOPCStorageVolumeCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumes()
name := d.Get("name").(string)
description := d.Get("description").(string)
size := d.Get("size").(int)
storageType := d.Get("storage_type").(string)
bootable := d.Get("bootable").(bool)
imageList := d.Get("image_list").(string)
imageListEntry := d.Get("image_list_entry").(int)
if bootable == true {
if imageList == "" {
return fmt.Errorf("Error: A Bootable Volume must have an Image List!")
}
if imageListEntry == -1 {
return fmt.Errorf("Error: A Bootable Volume must have an Image List Entry!")
}
}
input := compute.CreateStorageVolumeInput{
Name: name,
Description: description,
Size: strconv.Itoa(size),
Properties: []string{storageType},
Bootable: bootable,
ImageList: imageList,
ImageListEntry: imageListEntry,
Tags: getStringList(d, "tags"),
}
if v, ok := d.GetOk("snapshot"); ok {
input.Snapshot = v.(string)
}
if v, ok := d.GetOk("snapshot_account"); ok {
input.SnapshotAccount = v.(string)
}
if v, ok := d.GetOk("snapshot_id"); ok {
input.SnapshotID = v.(string)
}
info, err := client.CreateStorageVolume(&input)
if err != nil {
return fmt.Errorf("Error creating storage volume %s: %s", name, err)
}
d.SetId(info.Name)
return resourceOPCStorageVolumeRead(d, meta)
}
func resourceOPCStorageVolumeUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumes()
name := d.Id()
description := d.Get("description").(string)
size := d.Get("size").(int)
storageType := d.Get("storage_type").(string)
imageList := d.Get("image_list").(string)
imageListEntry := d.Get("image_list_entry").(int)
input := compute.UpdateStorageVolumeInput{
Name: name,
Description: description,
Size: strconv.Itoa(size),
Properties: []string{storageType},
ImageList: imageList,
ImageListEntry: imageListEntry,
Tags: getStringList(d, "tags"),
}
_, err := client.UpdateStorageVolume(&input)
if err != nil {
return fmt.Errorf("Error updating storage volume %s: %s", name, err)
}
return resourceOPCStorageVolumeRead(d, meta)
}
func resourceOPCStorageVolumeRead(d *schema.ResourceData, meta interface{}) error {
sv := meta.(*compute.Client).StorageVolumes()
name := d.Id()
input := compute.GetStorageVolumeInput{
Name: name,
}
result, err := sv.GetStorageVolume(&input)
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 result == nil {
// Volume doesn't exist
d.SetId("")
return nil
}
d.Set("name", result.Name)
d.Set("description", result.Description)
d.Set("storage_type", result.Properties[0])
size, err := strconv.Atoi(result.Size)
if err != nil {
return err
}
d.Set("size", size)
d.Set("bootable", result.Bootable)
d.Set("image_list", result.ImageList)
d.Set("image_list_entry", result.ImageListEntry)
d.Set("snapshot", result.Snapshot)
d.Set("snapshot_id", result.SnapshotID)
d.Set("snapshot_account", result.SnapshotAccount)
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
flattenOPCStorageVolumeComputedFields(d, result)
return nil
}
func resourceOPCStorageVolumeDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumes()
name := d.Id()
input := compute.DeleteStorageVolumeInput{
Name: name,
}
err := client.DeleteStorageVolume(&input)
if err != nil {
return fmt.Errorf("Error deleting storage volume %s: %s", name, err)
}
return nil
}
func flattenOPCStorageVolumeComputedFields(d *schema.ResourceData, result *compute.StorageVolumeInfo) {
d.Set("hypervisor", result.Hypervisor)
d.Set("machine_image", result.MachineImage)
d.Set("managed", result.Managed)
d.Set("platform", result.Platform)
d.Set("readonly", result.ReadOnly)
d.Set("status", result.Status)
d.Set("storage_pool", result.StoragePool)
d.Set("uri", result.URI)
}

View File

@ -0,0 +1,230 @@
package opc
import (
"fmt"
"strconv"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCStorageVolumeSnapshot() *schema.Resource {
return &schema.Resource{
Create: resourceOPCStorageVolumeSnapshotCreate,
Read: resourceOPCStorageVolumeSnapshotRead,
Delete: resourceOPCStorageVolumeSnapshotDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
// Required Attributes
"volume_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
// Optional Attributes
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
// Optional, but also computed if unspecified
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"parent_volume_bootable": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
},
"collocated": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"tags": tagsForceNewSchema(),
// Computed Attributes
"account": {
Type: schema.TypeString,
Computed: true,
},
"machine_image_name": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeString,
Computed: true,
},
"property": {
Type: schema.TypeString,
Computed: true,
},
"platform": {
Type: schema.TypeString,
Computed: true,
},
"snapshot_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
"start_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"status_detail": {
Type: schema.TypeString,
Computed: true,
},
"status_timestamp": {
Type: schema.TypeString,
Computed: true,
},
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOPCStorageVolumeSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumeSnapshots()
// Get required attribute
input := &compute.CreateStorageVolumeSnapshotInput{
Volume: d.Get("volume_name").(string),
}
if v, ok := d.GetOk("description"); ok {
input.Description = v.(string)
}
if v, ok := d.GetOk("name"); ok {
input.Name = v.(string)
}
// Convert parent_volume_bootable to string
bootable := d.Get("parent_volume_bootable").(bool)
if bootable {
input.ParentVolumeBootable = "true"
}
collocated := d.Get("collocated").(bool)
if collocated {
input.Property = compute.SnapshotPropertyCollocated
}
tags := getStringList(d, "tags")
if len(tags) > 0 {
input.Tags = tags
}
info, err := client.CreateStorageVolumeSnapshot(input)
if err != nil {
return fmt.Errorf("Error creating snapshot '%s': %v", input.Name, err)
}
d.SetId(info.Name)
return resourceOPCStorageVolumeSnapshotRead(d, meta)
}
func resourceOPCStorageVolumeSnapshotRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumeSnapshots()
name := d.Id()
input := &compute.GetStorageVolumeSnapshotInput{
Name: name,
}
result, err := client.GetStorageVolumeSnapshot(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading storage volume snapshot '%s': %v", name, err)
}
d.Set("volume_name", result.Volume)
d.Set("description", result.Description)
d.Set("name", result.Name)
d.Set("property", result.Property)
d.Set("platform", result.Platform)
d.Set("account", result.Account)
d.Set("machine_image_name", result.MachineImageName)
d.Set("size", result.Size)
d.Set("snapshot_timestamp", result.SnapshotTimestamp)
d.Set("snapshot_id", result.SnapshotID)
d.Set("start_timestamp", result.StartTimestamp)
d.Set("status", result.Status)
d.Set("status_detail", result.StatusDetail)
d.Set("status_timestamp", result.StatusTimestamp)
d.Set("uri", result.URI)
bootable, err := strconv.ParseBool(result.ParentVolumeBootable)
if err != nil {
return fmt.Errorf("Error converting parent volume to boolean: %v", err)
}
d.Set("parent_volume_bootable", bootable)
if result.Property != compute.SnapshotPropertyCollocated {
d.Set("collocated", false)
} else {
d.Set("collocated", true)
}
if err := setStringList(d, "tags", result.Tags); err != nil {
return err
}
return nil
}
func resourceOPCStorageVolumeSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).StorageVolumeSnapshots()
name := d.Id()
input := &compute.DeleteStorageVolumeSnapshotInput{
Name: name,
}
if err := client.DeleteStorageVolumeSnapshot(input); err != nil {
return fmt.Errorf("Error deleting storage volume snapshot '%s': %v", name, err)
}
return nil
}

View File

@ -0,0 +1,88 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCStorageVolumeSnapshot_basic(t *testing.T) {
snapshotName := "opc_compute_storage_volume_snapshot.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(snapshotName, testAccCheckStorageVolumeSnapshotDestroyed),
Steps: []resource.TestStep{
{
Config: testAccStorageVolumeSnapshot_basic(rInt),
Check: resource.ComposeTestCheckFunc(opcResourceCheck(snapshotName, testAccCheckStorageVolumeSnapshotExists),
resource.TestCheckResourceAttr(snapshotName, "name", fmt.Sprintf("test-acc-stor-vol-%d", rInt)),
resource.TestCheckResourceAttr(snapshotName, "parent_volume_bootable", "false"),
resource.TestCheckResourceAttr(snapshotName, "collocated", "true"),
resource.TestCheckResourceAttr(snapshotName, "size", "5"),
),
},
},
})
}
func testAccCheckStorageVolumeSnapshotExists(state *OPCResourceState) error {
client := state.Client.StorageVolumeSnapshots()
snapshotName := state.Attributes["name"]
input := &compute.GetStorageVolumeSnapshotInput{
Name: snapshotName,
}
info, err := client.GetStorageVolumeSnapshot(input)
if err != nil {
return fmt.Errorf("Error retrieving state of snapshot '%s': %v", snapshotName, err)
}
if info == nil {
return fmt.Errorf("No info found for snapshot '%s'", snapshotName)
}
return nil
}
func testAccCheckStorageVolumeSnapshotDestroyed(state *OPCResourceState) error {
client := state.Client.StorageVolumeSnapshots()
snapshotName := state.Attributes["name"]
input := &compute.GetStorageVolumeSnapshotInput{
Name: snapshotName,
}
info, err := client.GetStorageVolumeSnapshot(input)
if err != nil {
return fmt.Errorf("Error retrieving state of snapshot '%s': %v", snapshotName, err)
}
if info != nil {
return fmt.Errorf("Snapshot '%s' still exists", snapshotName)
}
return nil
}
func testAccStorageVolumeSnapshot_basic(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_storage_volume" "foo" {
name = "test-acc-stor-vol-%d"
description = "testAccStorageVolumeSnapshot_basic"
size = 5
}
resource "opc_compute_storage_volume_snapshot" "test" {
name = "test-acc-stor-vol-%d"
description = "storage volume snapshot"
collocated = true
volume_name = "${opc_compute_storage_volume.foo.name}"
}
`, rInt, rInt)
}

View File

@ -0,0 +1,333 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccOPCStorageVolume_Basic(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBasic, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_Complete(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeComplete, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_MaxSize(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBasicMaxSize, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_Update(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeComplete, ri)
updatedConfig := fmt.Sprintf(testAccStorageVolumeUpdated, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_Bootable(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeBootable, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_ImageListEntry(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
ri := acctest.RandInt()
config := fmt.Sprintf(testAccStorageVolumeImageListEntry, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
),
},
},
})
}
func TestAccOPCStorageVolume_LowLatency(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: testAccStorageVolumeLowLatency(rInt),
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
resource.TestCheckResourceAttr(volumeResourceName, "storage_type", "/oracle/public/storage/latency"),
),
},
},
})
}
func TestAccOPCStorageVolume_FromSnapshot(t *testing.T) {
volumeResourceName := "opc_compute_storage_volume.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeDestroyed),
Steps: []resource.TestStep{
{
Config: testAccStorageVolumeFromSnapshot(rInt),
Check: resource.ComposeTestCheckFunc(
opcResourceCheck(volumeResourceName, testAccCheckStorageVolumeExists),
resource.TestCheckResourceAttr(volumeResourceName, "name", fmt.Sprintf("test-acc-stor-vol-final-%d", rInt)),
resource.TestCheckResourceAttrSet(volumeResourceName, "snapshot"),
resource.TestCheckResourceAttrSet(volumeResourceName, "snapshot_id"),
resource.TestCheckResourceAttr(volumeResourceName, "size", "5"),
),
},
},
})
}
func testAccCheckStorageVolumeExists(state *OPCResourceState) error {
sv := state.Client.StorageVolumes()
volumeName := state.Attributes["name"]
input := compute.GetStorageVolumeInput{
Name: volumeName,
}
info, err := sv.GetStorageVolume(&input)
if err != nil {
return fmt.Errorf("Error retrieving state of volume %s: %s", volumeName, err)
}
if info == nil {
return fmt.Errorf("No info found for volume %s", volumeName)
}
return nil
}
func testAccCheckStorageVolumeDestroyed(state *OPCResourceState) error {
sv := state.Client.StorageVolumes()
volumeName := state.Attributes["name"]
input := compute.GetStorageVolumeInput{
Name: volumeName,
}
info, err := sv.GetStorageVolume(&input)
if err != nil {
return fmt.Errorf("Error retrieving state of volume %s: %s", volumeName, err)
}
if info != nil {
return fmt.Errorf("Volume %s still exists", volumeName)
}
return nil
}
const testAccStorageVolumeBasic = `
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-%d"
size = 1
}
`
const testAccStorageVolumeComplete = `
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-%d"
description = "Provider Acceptance Tests Storage Volume Initial"
size = 2
tags = ["foo"]
}
`
const testAccStorageVolumeUpdated = `
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-%d"
description = "Provider Acceptance Tests Storage Volume Updated"
size = 2
tags = ["bar", "foo"]
}
`
const testAccStorageVolumeBootable = `
resource "opc_compute_image_list" "test" {
name = "test-acc-stor-vol-bootable-image-list-%d"
description = "Provider Acceptance Tests Storage Volume Bootable"
}
resource "opc_compute_image_list_entry" "test" {
name = "${opc_compute_image_list.test.name}"
machine_images = [ "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" ]
version = 1
}
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-bootable-%d"
description = "Provider Acceptance Tests Storage Volume Bootable"
size = 20
tags = ["bar", "foo"]
bootable = true
image_list = "${opc_compute_image_list.test.name}"
image_list_entry = "${opc_compute_image_list_entry.test.version}"
}
`
const testAccStorageVolumeImageListEntry = `
resource "opc_compute_image_list" "test" {
name = "test-acc-stor-vol-bootable-image-list-%d"
description = "Provider Acceptance Tests Storage Volume Image List Entry"
}
resource "opc_compute_image_list_entry" "test" {
name = "${opc_compute_image_list.test.name}"
machine_images = [ "/oracle/public/oel_6.7_apaas_16.4.5_1610211300" ]
version = 1
}
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-image-list-entry-%d"
description = "Provider Acceptance Tests Storage Volume Image List Entry"
size = 20
tags = ["bar", "foo"]
image_list_entry = "${opc_compute_image_list_entry.test.version}"
}
`
const testAccStorageVolumeBasicMaxSize = `
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-%d"
description = "Provider Acceptance Tests Storage Volume Max Size"
size = 2048
}
`
func testAccStorageVolumeFromSnapshot(rInt int) string {
return fmt.Sprintf(`
// Initial Storage Volume to create snapshot with
resource "opc_compute_storage_volume" "foo" {
name = "test-acc-stor-vol-%d"
description = "Acc Test intermediary storage volume for snapshot"
size = 5
}
resource "opc_compute_storage_volume_snapshot" "foo" {
description = "testing-acc"
name = "test-acc-stor-snapshot-%d"
collocated = true
volume_name = "${opc_compute_storage_volume.foo.name}"
}
// Create storage volume from snapshot
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-final-%d"
description = "storage volume from snapshot"
size = 5
snapshot_id = "${opc_compute_storage_volume_snapshot.foo.snapshot_id}"
}`, rInt, rInt, rInt)
}
func testAccStorageVolumeLowLatency(rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_storage_volume" "test" {
name = "test-acc-stor-vol-ll-%d"
description = "Acc Test Storage Volume Low Latency"
storage_type = "/oracle/public/storage/latency"
size = 5
}`, rInt)
}

View File

@ -0,0 +1,169 @@
package opc
import (
"fmt"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceOPCVNICSet() *schema.Resource {
return &schema.Resource{
Create: resourceOPCVNICSetCreate,
Read: resourceOPCVNICSetRead,
Update: resourceOPCVNICSetUpdate,
Delete: resourceOPCVNICSetDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"applied_acls": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"virtual_nics": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"tags": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}
func resourceOPCVNICSetCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).VirtNICSets()
name := d.Get("name").(string)
desc, descOk := d.GetOk("description")
input := &compute.CreateVirtualNICSetInput{
Name: name,
}
if descOk {
input.Description = desc.(string)
}
acls := getStringList(d, "applied_acls")
if len(acls) != 0 {
input.AppliedACLs = acls
}
vnics := getStringList(d, "virtual_nics")
if len(vnics) != 0 {
input.VirtualNICs = vnics
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
vnicSet, err := client.CreateVirtualNICSet(input)
if err != nil {
return fmt.Errorf("Error creating Virtual NIC Set: %s", err)
}
d.SetId(vnicSet.Name)
return resourceOPCVNICSetRead(d, meta)
}
func resourceOPCVNICSetRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).VirtNICSets()
name := d.Id()
input := &compute.GetVirtualNICSetInput{
Name: name,
}
res, err := client.GetVirtualNICSet(input)
if err != nil {
if compute.WasNotFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading Virtual NIC Set '%s': %s", name, err)
}
d.Set("name", res.Name)
d.Set("description", res.Description)
if err := setStringList(d, "applied_acls", res.AppliedACLs); err != nil {
return err
}
if err := setStringList(d, "virtual_nics", res.VirtualNICs); err != nil {
return err
}
if err := setStringList(d, "tags", res.Tags); err != nil {
return err
}
return nil
}
func resourceOPCVNICSetUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).VirtNICSets()
name := d.Id()
desc, descOk := d.GetOk("description")
input := &compute.UpdateVirtualNICSetInput{
Name: name,
}
if descOk {
input.Description = desc.(string)
}
acls := getStringList(d, "applied_acls")
if len(acls) != 0 {
input.AppliedACLs = acls
}
vnics := getStringList(d, "virtual_nics")
if len(vnics) != 0 {
input.VirtualNICs = vnics
}
tags := getStringList(d, "tags")
if len(tags) != 0 {
input.Tags = tags
}
info, err := client.UpdateVirtualNICSet(input)
if err != nil {
return fmt.Errorf("Error updating Virtual NIC Set: %s", err)
}
d.SetId(info.Name)
return resourceOPCVNICSetRead(d, meta)
}
func resourceOPCVNICSetDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*compute.Client).VirtNICSets()
name := d.Id()
input := &compute.DeleteVirtualNICSetInput{
Name: name,
}
if err := client.DeleteVirtualNICSet(input); err != nil {
return fmt.Errorf("Error deleting Virtual NIC Set '%s': %s", name, err)
}
return nil
}

View File

@ -0,0 +1,203 @@
package opc
import (
"fmt"
"testing"
"github.com/hashicorp/go-oracle-terraform/compute"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccOPCVNICSet_Basic(t *testing.T) {
rInt := acctest.RandInt()
rName := fmt.Sprintf("testing-acc-%d", rInt)
rDesc := fmt.Sprintf("acctesting vnic set %d", rInt)
resourceName := "opc_compute_vnic_set.test"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccOPCCheckVNICSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccVnicSetBasic(rName, rDesc, rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckVNICSetExists,
resource.TestCheckResourceAttr(
resourceName, "name", rName),
resource.TestCheckResourceAttr(
resourceName, "description", rDesc),
resource.TestCheckResourceAttr(
resourceName, "tags.#", "2"),
resource.TestCheckResourceAttr(
resourceName, "virtual_nics.#", "2"),
),
},
{
Config: testAccVnicSetBasic_Update(rName, rDesc, rInt),
Check: resource.ComposeTestCheckFunc(
testAccOPCCheckVNICSetExists,
resource.TestCheckResourceAttr(
resourceName, "name", rName),
resource.TestCheckResourceAttr(
resourceName, "description", fmt.Sprintf("%s-updated", rDesc)),
resource.TestCheckResourceAttr(
resourceName, "tags.#", "1"),
resource.TestCheckResourceAttr(
resourceName, "virtual_nics.#", "2"),
),
},
},
})
}
func testAccOPCCheckVNICSetExists(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).VirtNICSets()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_vnic_set" {
continue
}
input := compute.GetVirtualNICSetInput{
Name: rs.Primary.Attributes["name"],
}
if _, err := client.GetVirtualNICSet(&input); err != nil {
return fmt.Errorf("Error retrieving state of VNIC Set %s: %s", input.Name, err)
}
}
return nil
}
func testAccOPCCheckVNICSetDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*compute.Client).VirtNICSets()
for _, rs := range s.RootModule().Resources {
if rs.Type != "opc_compute_vnic_set" {
continue
}
input := compute.GetVirtualNICSetInput{
Name: rs.Primary.Attributes["name"],
}
if info, err := client.GetVirtualNICSet(&input); err == nil {
return fmt.Errorf("VNIC Set %s still exists: %#v", input.Name, info)
}
}
return nil
}
func testAccVnicSetBasic(rName, rDesc string, rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-vnic-set-%d"
description = "testing-vnic-set"
ip_address_prefix = "10.1.14.0/24"
}
resource "opc_compute_ip_network" "bar" {
name = "testing-vnic-set2-%d"
description = "testing-vnic-set2"
ip_address_prefix = "10.1.15.0/24"
}
resource "opc_compute_instance" "foo" {
name = "test-vnic-set-%d"
label = "testing"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-set-%d"
shared_network = false
}
networking_info {
index = 1
ip_network = "${opc_compute_ip_network.bar.id}"
vnic = "test-vnic-set2-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "foo" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth0"
}
data "opc_compute_network_interface" "bar" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth1"
}
resource "opc_compute_vnic_set" "test" {
name = "%s"
description = "%s"
tags = ["tag1", "tag2"]
virtual_nics = [
"${data.opc_compute_network_interface.foo.vnic}",
"${data.opc_compute_network_interface.bar.vnic}",
]
}`, rInt, rInt, rInt, rInt, rInt, rName, rDesc)
}
func testAccVnicSetBasic_Update(rName, rDesc string, rInt int) string {
return fmt.Sprintf(`
resource "opc_compute_ip_network" "foo" {
name = "testing-vnic-set-%d"
description = "testing-vnic-set"
ip_address_prefix = "10.1.14.0/24"
}
resource "opc_compute_ip_network" "bar" {
name = "testing-vnic-set2-%d"
description = "testing-vnic-set2"
ip_address_prefix = "10.1.15.0/24"
}
resource "opc_compute_instance" "foo" {
name = "test-vnic-set-%d"
label = "testing"
shape = "oc3"
image_list = "/oracle/public/oel_6.7_apaas_16.4.5_1610211300"
networking_info {
index = 0
ip_network = "${opc_compute_ip_network.foo.id}"
vnic = "test-vnic-set-%d"
shared_network = false
}
networking_info {
index = 1
ip_network = "${opc_compute_ip_network.bar.id}"
vnic = "test-vnic-set2-%d"
shared_network = false
}
}
data "opc_compute_network_interface" "foo" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth0"
}
data "opc_compute_network_interface" "bar" {
instance_name = "${opc_compute_instance.foo.name}"
instance_id = "${opc_compute_instance.foo.id}"
interface = "eth1"
}
resource "opc_compute_vnic_set" "test" {
name = "%s"
description = "%s-updated"
tags = ["tag1"]
virtual_nics = [
"${data.opc_compute_network_interface.foo.vnic}",
"${data.opc_compute_network_interface.bar.vnic}",
]
}`, rInt, rInt, rInt, rInt, rInt, rName, rDesc)
}

View File

@ -0,0 +1,28 @@
package opc
import "github.com/hashicorp/terraform/helper/schema"
func tagsOptionalSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
}
}
func tagsForceNewSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
}
}
func tagsComputedSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
}
}

View File

@ -0,0 +1,67 @@
package opc
import (
"fmt"
"net"
"github.com/hashicorp/go-oracle-terraform/compute"
)
// Validate whether an IP Prefix CIDR is correct or not
func validateIPPrefixCIDR(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
_, ipnet, err := net.ParseCIDR(value)
if err != nil {
errors = append(errors, fmt.Errorf(
"%q must contain a valid CIDR, got error while parsing: %s", k, err))
return
}
if ipnet == nil || value != ipnet.String() {
errors = append(errors, fmt.Errorf(
"%q must contain a valid network CIDR, expected %q, got %q", k, ipnet, value))
return
}
return
}
// Admin distance can either be a 0, 1, or a 2. Defaults to 0.
func validateAdminDistance(v interface{}, k string) (ws []string, errors []error) {
value := v.(int)
if value < 0 || value > 2 {
errors = append(errors, fmt.Errorf(
"%q can only be an interger between 0-2. Got: %d", k, value))
}
return
}
// Admin distance can either be a 0, 1, or a 2. Defaults to 0.
func validateIPProtocol(v interface{}, k string) (ws []string, errors []error) {
validProtocols := map[string]struct{}{
string(compute.All): {},
string(compute.AH): {},
string(compute.ESP): {},
string(compute.ICMP): {},
string(compute.ICMPV6): {},
string(compute.IGMP): {},
string(compute.IPIP): {},
string(compute.GRE): {},
string(compute.MPLSIP): {},
string(compute.OSPF): {},
string(compute.PIM): {},
string(compute.RDP): {},
string(compute.SCTP): {},
string(compute.TCP): {},
string(compute.UDP): {},
}
value := v.(string)
if _, ok := validProtocols[value]; !ok {
errors = append(errors, fmt.Errorf(
`%q must contain a valid Image owner , expected ["all", "ah", "esp", "icmp", "icmpv6", "igmp", "ipip", "gre", "mplsip", "ospf", "pim", "rdp", "sctp", "tcp", "udp"] got %q`,
k, value))
}
return
}

View File

@ -0,0 +1,102 @@
package opc
import "testing"
func TestValidateIPPrefixCIDR(t *testing.T) {
validPrefixes := []string{
"10.0.1.0/24",
"10.1.0.0/16",
"192.168.0.1/32",
"10.20.0.0/18",
"10.0.12.0/24",
}
for _, v := range validPrefixes {
_, errors := validateIPPrefixCIDR(v, "prefix")
if len(errors) != 0 {
t.Fatalf("%q should be a valid IP Address Prefix: %q", v, errors)
}
}
invalidPrefixes := []string{
"10.0.0.1/35",
"192.168.1.256/16",
"256.0.1/16",
}
for _, v := range invalidPrefixes {
_, errors := validateIPPrefixCIDR(v, "prefix")
if len(errors) == 0 {
t.Fatalf("%q should not be a valid IP Address", v)
}
}
}
func TestValidateAdminDistance(t *testing.T) {
validDistances := []int{
0,
1,
2,
}
for _, v := range validDistances {
_, errors := validateAdminDistance(v, "distance")
if len(errors) != 0 {
t.Fatalf("%q should be a valid Admin Distance: %q", v, errors)
}
}
invalidDistances := []int{
-1,
4,
3,
42,
}
for _, v := range invalidDistances {
_, errors := validateAdminDistance(v, "distance")
if len(errors) == 0 {
t.Fatalf("%q should not be a valid Admin Distance", v)
}
}
}
func TestValidateIPProtocol(t *testing.T) {
validProtocols := []string{
"all",
"ah",
"esp",
"icmp",
"icmpv6",
"igmp",
"ipip",
"gre",
"mplsip",
"ospf",
"pim",
"rdp",
"sctp",
"tcp",
"udp",
}
for _, v := range validProtocols {
_, errors := validateIPProtocol(v, "ip_protocol")
if len(errors) != 0 {
t.Fatalf("%q should be a valid Admin Distance: %q", v, errors)
}
}
invalidProtocols := []string{
"bad",
"real bad",
"are you even trying at this point?",
}
for _, v := range invalidProtocols {
_, errors := validateIPProtocol(v, "ip_protocol")
if len(errors) == 0 {
t.Fatalf("%q should not be a valid IP Protocol", v)
}
}
}

View File

@ -47,6 +47,7 @@ import (
nomadprovider "github.com/hashicorp/terraform/builtin/providers/nomad"
ns1provider "github.com/hashicorp/terraform/builtin/providers/ns1"
nullprovider "github.com/hashicorp/terraform/builtin/providers/null"
opcprovider "github.com/hashicorp/terraform/builtin/providers/opc"
openstackprovider "github.com/hashicorp/terraform/builtin/providers/openstack"
opsgenieprovider "github.com/hashicorp/terraform/builtin/providers/opsgenie"
packetprovider "github.com/hashicorp/terraform/builtin/providers/packet"
@ -124,6 +125,7 @@ var InternalProviders = map[string]plugin.ProviderFunc{
"nomad": nomadprovider.Provider,
"ns1": ns1provider.Provider,
"null": nullprovider.Provider,
"opc": opcprovider.Provider,
"openstack": openstackprovider.Provider,
"opsgenie": opsgenieprovider.Provider,
"packet": packetprovider.Provider,

373
vendor/github.com/hashicorp/go-oracle-terraform/LICENSE generated vendored Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

View File

@ -0,0 +1,138 @@
package compute
// ACLsClient is a client for the ACLs functions of the Compute API.
type ACLsClient struct {
ResourceClient
}
const (
ACLDescription = "acl"
ACLContainerPath = "/network/v1/acl/"
ACLResourcePath = "/network/v1/acl"
)
// ACLs obtains a ACLsClient which can be used to access to the
// ACLs functions of the Compute API
func (c *Client) ACLs() *ACLsClient {
return &ACLsClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: ACLDescription,
ContainerPath: ACLContainerPath,
ResourceRootPath: ACLResourcePath,
}}
}
// ACLInfo describes an existing ACL.
type ACLInfo struct {
// Description of the ACL
Description string `json:"description"`
// Indicates whether the ACL is enabled
Enabled bool `json:"enabledFlag"`
// The name of the ACL
Name string `json:"name"`
// Tags associated with the ACL
Tags []string `json:"tags"`
// Uniform Resource Identifier for the ACL
URI string `json:"uri"`
}
// CreateACLInput defines a ACL to be created.
type CreateACLInput struct {
// Description of the ACL
// Optional
Description string `json:"description"`
// Enables or disables the ACL. Set to true by default.
//Set this to false to disable the ACL.
// Optional
Enabled bool `json:"enabledFlag"`
// The name of the ACL to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Strings that you can use to tag the ACL.
// Optional
Tags []string `json:"tags"`
}
// CreateACL creates a new ACL.
func (c *ACLsClient) CreateACL(createInput *CreateACLInput) (*ACLInfo, error) {
createInput.Name = c.getQualifiedName(createInput.Name)
var aclInfo ACLInfo
if err := c.createResource(createInput, &aclInfo); err != nil {
return nil, err
}
return c.success(&aclInfo)
}
// GetACLInput describes the ACL to get
type GetACLInput struct {
// The name of the ACL to query for
// Required
Name string `json:"name"`
}
// GetACL retrieves the ACL with the given name.
func (c *ACLsClient) GetACL(getInput *GetACLInput) (*ACLInfo, error) {
var aclInfo ACLInfo
if err := c.getResource(getInput.Name, &aclInfo); err != nil {
return nil, err
}
return c.success(&aclInfo)
}
// UpdateACLInput describes a secruity rule to update
type UpdateACLInput struct {
// Description of the ACL
// Optional
Description string `json:"description"`
// Enables or disables the ACL. Set to true by default.
//Set this to false to disable the ACL.
// Optional
Enabled bool `json:"enabledFlag"`
// The name of the ACL to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Strings that you can use to tag the ACL.
// Optional
Tags []string `json:"tags"`
}
// UpdateACL modifies the properties of the ACL with the given name.
func (c *ACLsClient) UpdateACL(updateInput *UpdateACLInput) (*ACLInfo, error) {
updateInput.Name = c.getQualifiedName(updateInput.Name)
var aclInfo ACLInfo
if err := c.updateResource(updateInput.Name, updateInput, &aclInfo); err != nil {
return nil, err
}
return c.success(&aclInfo)
}
// DeleteACLInput describes the ACL to delete
type DeleteACLInput struct {
// The name of the ACL to delete.
// Required
Name string `json:"name"`
}
// DeleteACL deletes the ACL with the given name.
func (c *ACLsClient) DeleteACL(deleteInput *DeleteACLInput) error {
return c.deleteResource(deleteInput.Name)
}
func (c *ACLsClient) success(aclInfo *ACLInfo) (*ACLInfo, error) {
aclInfo.Name = c.getUnqualifiedName(aclInfo.Name)
return aclInfo, nil
}

View File

@ -0,0 +1,34 @@
package compute
import (
"fmt"
"time"
)
// AuthenticationReq represents the body of an authentication request.
type AuthenticationReq struct {
User string `json:"user"`
Password string `json:"password"`
}
// Get a new auth cookie for the compute client
func (c *Client) getAuthenticationCookie() error {
req := AuthenticationReq{
User: c.getUserName(),
Password: *c.password,
}
rsp, err := c.executeRequest("POST", "/authenticate/", req)
if err != nil {
return err
}
if len(rsp.Cookies()) == 0 {
return fmt.Errorf("No authentication cookie found in response %#v", rsp)
}
c.debugLogString("Successfully authenticated to OPC")
c.authCookie = rsp.Cookies()[0]
c.cookieIssued = time.Now()
return nil
}

View File

@ -0,0 +1,240 @@
package compute
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
"strings"
"time"
"github.com/hashicorp/go-oracle-terraform/opc"
)
const CMP_USERNAME = "/Compute-%s/%s"
const CMP_QUALIFIED_NAME = "%s/%s"
// Client represents an authenticated compute client, with compute credentials and an api client.
type Client struct {
identityDomain *string
userName *string
password *string
apiEndpoint *url.URL
httpClient *http.Client
authCookie *http.Cookie
cookieIssued time.Time
logger opc.Logger
loglevel opc.LogLevelType
}
func NewComputeClient(c *opc.Config) (*Client, error) {
// First create a client
client := &Client{
identityDomain: c.IdentityDomain,
userName: c.Username,
password: c.Password,
apiEndpoint: c.APIEndpoint,
httpClient: c.HTTPClient,
loglevel: c.LogLevel,
}
// Setup logger; defaults to stdout
if c.Logger == nil {
client.logger = opc.NewDefaultLogger()
} else {
client.logger = c.Logger
}
// If LogLevel was not set to something different,
// double check for env var
if c.LogLevel == 0 {
client.loglevel = opc.LogLevel()
}
if err := client.getAuthenticationCookie(); err != nil {
return nil, err
}
return client, nil
}
func (c *Client) executeRequest(method, path string, body interface{}) (*http.Response, error) {
// Parse URL Path
urlPath, err := url.Parse(path)
if err != nil {
return nil, err
}
// Marshall request body
var requestBody io.ReadSeeker
var marshaled []byte
if body != nil {
marshaled, err = json.Marshal(body)
if err != nil {
return nil, err
}
requestBody = bytes.NewReader(marshaled)
}
// Create request
req, err := http.NewRequest(method, c.formatURL(urlPath), requestBody)
if err != nil {
return nil, err
}
debugReqString := fmt.Sprintf("HTTP %s Req (%s)", method, path)
if body != nil {
req.Header.Set("Content-Type", "application/oracle-compute-v3+json")
// Don't leak creds in STDERR
if path != "/authenticate/" {
debugReqString = fmt.Sprintf("%s:\n %s", debugReqString, string(marshaled))
}
}
// Log the request before the authentication cookie, so as not to leak credentials
c.debugLogString(debugReqString)
// If we have an authentication cookie, let's authenticate, refreshing cookie if need be
if c.authCookie != nil {
if time.Since(c.cookieIssued).Minutes() > 25 {
if err := c.getAuthenticationCookie(); err != nil {
return nil, err
}
}
req.AddCookie(c.authCookie)
}
// Execute request with supplied client
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices {
return resp, nil
}
oracleErr := &opc.OracleError{
StatusCode: resp.StatusCode,
}
// Even though the returned body will be in json form, it's undocumented what
// fields are actually returned. Once we get documentation of the actual
// error fields that are possible to be returned we can have stricter error types.
if resp.Body != nil {
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
oracleErr.Message = buf.String()
}
return nil, oracleErr
}
func (c *Client) formatURL(path *url.URL) string {
return c.apiEndpoint.ResolveReference(path).String()
}
func (c *Client) getUserName() string {
return fmt.Sprintf(CMP_USERNAME, *c.identityDomain, *c.userName)
}
// From compute_client
// GetObjectName returns the fully-qualified name of an OPC object, e.g. /identity-domain/user@email/{name}
func (c *Client) getQualifiedName(name string) string {
if name == "" {
return ""
}
if strings.HasPrefix(name, "/oracle") || strings.HasPrefix(name, "/Compute-") {
return name
}
return fmt.Sprintf(CMP_QUALIFIED_NAME, c.getUserName(), name)
}
func (c *Client) getObjectPath(root, name string) string {
return fmt.Sprintf("%s%s", root, c.getQualifiedName(name))
}
// GetUnqualifiedName returns the unqualified name of an OPC object, e.g. the {name} part of /identity-domain/user@email/{name}
func (c *Client) getUnqualifiedName(name string) string {
if name == "" {
return name
}
if strings.HasPrefix(name, "/oracle") {
return name
}
if !strings.Contains(name, "/") {
return name
}
nameParts := strings.Split(name, "/")
return strings.Join(nameParts[3:], "/")
}
func (c *Client) unqualify(names ...*string) {
for _, name := range names {
*name = c.getUnqualifiedName(*name)
}
}
func (c *Client) unqualifyUrl(url *string) {
var validID = regexp.MustCompile(`(\/(Compute[^\/\s]+))(\/[^\/\s]+)(\/[^\/\s]+)`)
name := validID.FindString(*url)
*url = c.getUnqualifiedName(name)
}
func (c *Client) getQualifiedList(list []string) []string {
for i, name := range list {
list[i] = c.getQualifiedName(name)
}
return list
}
func (c *Client) getUnqualifiedList(list []string) []string {
for i, name := range list {
list[i] = c.getUnqualifiedName(name)
}
return list
}
func (c *Client) getQualifiedListName(name string) string {
nameParts := strings.Split(name, ":")
listType := nameParts[0]
listName := nameParts[1]
return fmt.Sprintf("%s:%s", listType, c.getQualifiedName(listName))
}
func (c *Client) unqualifyListName(qualifiedName string) string {
nameParts := strings.Split(qualifiedName, ":")
listType := nameParts[0]
listName := nameParts[1]
return fmt.Sprintf("%s:%s", listType, c.getUnqualifiedName(listName))
}
// Retry function
func (c *Client) waitFor(description string, timeoutSeconds int, test func() (bool, error)) error {
tick := time.Tick(1 * time.Second)
for i := 0; i < timeoutSeconds; i++ {
select {
case <-tick:
completed, err := test()
c.debugLogString(fmt.Sprintf("Waiting for %s (%d/%ds)", description, i, timeoutSeconds))
if err != nil || completed {
return err
}
}
}
return fmt.Errorf("Timeout waiting for %s", description)
}
// Used to determine if the checked resource was found or not.
func WasNotFoundError(e error) bool {
err, ok := e.(*opc.OracleError)
if ok {
return err.StatusCode == 404
}
return false
}

View File

@ -0,0 +1,154 @@
package compute
const (
ImageListDescription = "Image List"
ImageListContainerPath = "/imagelist/"
ImageListResourcePath = "/imagelist"
)
// ImageListClient is a client for the Image List functions of the Compute API.
type ImageListClient struct {
ResourceClient
}
// ImageList obtains an ImageListClient which can be used to access to the
// Image List functions of the Compute API
func (c *Client) ImageList() *ImageListClient {
return &ImageListClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: ImageListDescription,
ContainerPath: ImageListContainerPath,
ResourceRootPath: ImageListResourcePath,
}}
}
type ImageListEntry struct {
// User-defined parameters, in JSON format, that can be passed to an instance of this machine image when it is launched.
Attributes map[string]interface{} `json:"attributes"`
// Name of the Image List.
ImageList string `json:"imagelist"`
// A list of machine images.
MachineImages []string `json:"machineimages"`
// Uniform Resource Identifier.
URI string `json:"uri"`
// Version number of these Machine Images in the Image List.
Version int `json:"version"`
}
// ImageList describes an existing Image List.
type ImageList struct {
// The image list entry to be used, by default, when launching instances using this image list
Default int `json:"default"`
// A description of this image list.
Description string `json:"description"`
// Each machine image in an image list is identified by an image list entry.
Entries []ImageListEntry `json:"entries"`
// The name of the Image List
Name string `json:"name"`
// Uniform Resource Identifier
URI string `json:"uri"`
}
// CreateImageListInput defines an Image List to be created.
type CreateImageListInput struct {
// The image list entry to be used, by default, when launching instances using this image list.
// If you don't specify this value, it is set to 1.
// Optional
Default int `json:"default"`
// A description of this image list.
// Required
Description string `json:"description"`
// The name of the Image List
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods. Object names are case-sensitive.
// Required
Name string `json:"name"`
}
// CreateImageList creates a new Image List with the given name, key and enabled flag.
func (c *ImageListClient) CreateImageList(createInput *CreateImageListInput) (*ImageList, error) {
var imageList ImageList
createInput.Name = c.getQualifiedName(createInput.Name)
if err := c.createResource(&createInput, &imageList); err != nil {
return nil, err
}
return c.success(&imageList)
}
// DeleteKeyInput describes the image list to delete
type DeleteImageListInput struct {
// The name of the Image List
Name string `json:name`
}
// DeleteImageList deletes the Image List with the given name.
func (c *ImageListClient) DeleteImageList(deleteInput *DeleteImageListInput) error {
deleteInput.Name = c.getQualifiedName(deleteInput.Name)
return c.deleteResource(deleteInput.Name)
}
// GetImageListInput describes the image list to get
type GetImageListInput struct {
// The name of the Image List
Name string `json:name`
}
// GetImageList retrieves the Image List with the given name.
func (c *ImageListClient) GetImageList(getInput *GetImageListInput) (*ImageList, error) {
getInput.Name = c.getQualifiedName(getInput.Name)
var imageList ImageList
if err := c.getResource(getInput.Name, &imageList); err != nil {
return nil, err
}
return c.success(&imageList)
}
// UpdateImageListInput defines an Image List to be updated
type UpdateImageListInput struct {
// The image list entry to be used, by default, when launching instances using this image list.
// If you don't specify this value, it is set to 1.
// Optional
Default int `json:"default"`
// A description of this image list.
// Required
Description string `json:"description"`
// The name of the Image List
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods. Object names are case-sensitive.
// Required
Name string `json:"name"`
}
// UpdateImageList updates the key and enabled flag of the Image List with the given name.
func (c *ImageListClient) UpdateImageList(updateInput *UpdateImageListInput) (*ImageList, error) {
var imageList ImageList
updateInput.Name = c.getQualifiedName(updateInput.Name)
if err := c.updateResource(updateInput.Name, updateInput, &imageList); err != nil {
return nil, err
}
return c.success(&imageList)
}
func (c *ImageListClient) success(imageList *ImageList) (*ImageList, error) {
c.unqualify(&imageList.Name)
for _, v := range imageList.Entries {
v.MachineImages = c.getUnqualifiedList(v.MachineImages)
}
return imageList, nil
}

View File

@ -0,0 +1,122 @@
package compute
import "fmt"
const (
ImageListEntryDescription = "image list entry"
ImageListEntryContainerPath = "/imagelist"
ImageListEntryResourcePath = "/imagelist"
)
type ImageListEntriesClient struct {
ResourceClient
}
// ImageListEntries() returns an ImageListEntriesClient that can be used to access the
// necessary CRUD functions for Image List Entry's.
func (c *Client) ImageListEntries() *ImageListEntriesClient {
return &ImageListEntriesClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: ImageListEntryDescription,
ContainerPath: ImageListEntryContainerPath,
ResourceRootPath: ImageListEntryResourcePath,
},
}
}
// ImageListEntryInfo contains the exported fields necessary to hold all the information about an
// Image List Entry
type ImageListEntryInfo struct {
// User-defined parameters, in JSON format, that can be passed to an instance of this machine
// image when it is launched. This field can be used, for example, to specify the location of
// a database server and login details. Instance metadata, including user-defined data is available
// at http://192.0.0.192/ within an instance. See Retrieving User-Defined Instance Attributes in Using
// Oracle Compute Cloud Service (IaaS).
Attributes map[string]interface{} `json:"attributes"`
// Name of the imagelist.
Name string `json:"imagelist"`
// A list of machine images.
MachineImages []string `json:"machineimages"`
// Uniform Resource Identifier for the Image List Entry
Uri string `json:"uri"`
// Version number of these machineImages in the imagelist.
Version int `json:"version"`
}
type CreateImageListEntryInput struct {
// The name of the Image List
Name string
// User-defined parameters, in JSON format, that can be passed to an instance of this machine
// image when it is launched. This field can be used, for example, to specify the location of
// a database server and login details. Instance metadata, including user-defined data is
//available at http://192.0.0.192/ within an instance. See Retrieving User-Defined Instance
//Attributes in Using Oracle Compute Cloud Service (IaaS).
// Optional
Attributes map[string]interface{} `json:"attributes"`
// A list of machine images.
// Required
MachineImages []string `json:"machineimages"`
// The unique version of the entry in the image list.
// Required
Version int `json:"version"`
}
// Create a new Image List Entry from an ImageListEntriesClient and an input struct.
// Returns a populated Info struct for the Image List Entry, and any errors
func (c *ImageListEntriesClient) CreateImageListEntry(input *CreateImageListEntryInput) (*ImageListEntryInfo, error) {
c.updateClientPaths(input.Name, -1)
var imageListEntryInfo ImageListEntryInfo
if err := c.createResource(&input, &imageListEntryInfo); err != nil {
return nil, err
}
return c.success(&imageListEntryInfo)
}
type GetImageListEntryInput struct {
// The name of the Image List
Name string
// Version number of these machineImages in the imagelist.
Version int
}
// Returns a populated ImageListEntryInfo struct from an input struct
func (c *ImageListEntriesClient) GetImageListEntry(input *GetImageListEntryInput) (*ImageListEntryInfo, error) {
c.updateClientPaths(input.Name, input.Version)
var imageListEntryInfo ImageListEntryInfo
if err := c.getResource("", &imageListEntryInfo); err != nil {
return nil, err
}
return c.success(&imageListEntryInfo)
}
type DeleteImageListEntryInput struct {
// The name of the Image List
Name string
// Version number of these machineImages in the imagelist.
Version int
}
func (c *ImageListEntriesClient) DeleteImageListEntry(input *DeleteImageListEntryInput) error {
c.updateClientPaths(input.Name, input.Version)
return c.deleteResource("")
}
func (c *ImageListEntriesClient) updateClientPaths(name string, version int) {
var containerPath, resourcePath string
name = c.getQualifiedName(name)
containerPath = ImageListEntryContainerPath + name + "/entry/"
resourcePath = ImageListEntryContainerPath + name + "/entry"
if version != -1 {
containerPath = fmt.Sprintf("%s%d", containerPath, version)
resourcePath = fmt.Sprintf("%s/%d", resourcePath, version)
}
c.ContainerPath = containerPath
c.ResourceRootPath = resourcePath
}
// Unqualifies any qualified fields in the IPNetworkInfo struct
func (c *ImageListEntriesClient) success(info *ImageListEntryInfo) (*ImageListEntryInfo, error) {
c.unqualifyUrl(&info.Uri)
return info, nil
}

View File

@ -0,0 +1,553 @@
package compute
import (
"errors"
"fmt"
"strings"
)
const WaitForInstanceReadyTimeout = 600
const WaitForInstanceDeleteTimeout = 600
// InstancesClient is a client for the Instance functions of the Compute API.
type InstancesClient struct {
ResourceClient
}
// Instances obtains an InstancesClient which can be used to access to the
// Instance functions of the Compute API
func (c *Client) Instances() *InstancesClient {
return &InstancesClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: "instance",
ContainerPath: "/launchplan/",
ResourceRootPath: "/instance",
}}
}
type InstanceState string
const (
InstanceRunning InstanceState = "running"
InstanceInitializing InstanceState = "initializing"
InstancePreparing InstanceState = "preparing"
InstanceStopping InstanceState = "stopping"
InstanceQueued InstanceState = "queued"
InstanceError InstanceState = "error"
)
// InstanceInfo represents the Compute API's view of the state of an instance.
type InstanceInfo struct {
// The ID for the instance. Set by the SDK based on the request - not the API.
ID string
// A dictionary of attributes to be made available to the instance.
// A value with the key "userdata" will be made available in an EC2-compatible manner.
Attributes map[string]interface{} `json:"attributes"`
// The availability domain for the instance
AvailabilityDomain string `json:"availability_domain"`
// Boot order list.
BootOrder []int `json:"boot_order"`
// The default domain to use for the hostname and DNS lookups
Domain string `json:"domain"`
// Optional ImageListEntry number. Default will be used if not specified
Entry int `json:"entry"`
// The reason for the instance going to error state, if available.
ErrorReason string `json:"error_reason"`
// SSH Server Fingerprint presented by the instance
Fingerprint string `json:"fingerprint"`
// The hostname for the instance
Hostname string `json:"hostname"`
// The format of the image
ImageFormat string `json:"image_format"`
// Name of imagelist to be launched.
ImageList string `json:"imagelist"`
// IP address of the instance.
IPAddress string `json:"ip"`
// A label assigned by the user, specifically for defining inter-instance relationships.
Label string `json:"label"`
// Name of this instance, generated by the server.
Name string `json:"name"`
// Mapping of to network specifiers for virtual NICs to be attached to this instance.
Networking map[string]NetworkingInfo `json:"networking"`
// A list of strings specifying arbitrary tags on nodes to be matched on placement.
PlacementRequirements []string `json:"placement_requirements"`
// The OS platform for the instance.
Platform string `json:"platform"`
// The priority at which this instance will be run
Priority string `json:"priority"`
// Reference to the QuotaReservation, to be destroyed with the instance
QuotaReservation string `json:"quota_reservation"`
// Array of relationship specifications to be satisfied on this instance's placement
Relationships []string `json:"relationships"`
// Resolvers to use instead of the default resolvers
Resolvers []string `json:"resolvers"`
// Add PTR records for the hostname
ReverseDNS bool `json:"reverse_dns"`
// Type of instance, as defined on site configuration.
Shape string `json:"shape"`
// Site to run on
Site string `json:"site"`
// ID's of SSH keys that will be exposed to the instance.
SSHKeys []string `json:"sshkeys"`
// The start time of the instance
StartTime string `json:"start_time"`
// State of the instance.
State InstanceState `json:"state"`
// The Storage Attachment information.
Storage []StorageAttachment `json:"storage_attachments"`
// Array of tags associated with the instance.
Tags []string `json:"tags"`
// vCable for this instance.
VCableID string `json:"vcable_id"`
// Specify if the devices created for the instance are virtio devices. If not specified, the default
// will come from the cluster configuration file
Virtio bool `json:"virtio,omitempty"`
// IP Address and port of the VNC console for the instance
VNC string `json:"vnc"`
}
type StorageAttachment struct {
// The index number for the volume.
Index int `json:"index"`
// The three-part name (/Compute-identity_domain/user/object) of the storage attachment.
Name string `json:"name"`
// The three-part name (/Compute-identity_domain/user/object) of the storage volume attached to the instance.
StorageVolumeName string `json:"storage_volume_name"`
}
func (i *InstanceInfo) getInstanceName() string {
return fmt.Sprintf(CMP_QUALIFIED_NAME, i.Name, i.ID)
}
type CreateInstanceInput struct {
// A dictionary of user-defined attributes to be made available to the instance.
// Optional
Attributes map[string]interface{} `json:"attributes"`
// Boot order list
// Optional
BootOrder []int `json:"boot_order"`
// The host name assigned to the instance. On an Oracle Linux instance,
// this host name is displayed in response to the hostname command.
// Only relative DNS is supported. The domain name is suffixed to the host name
// that you specify. The host name must not end with a period. If you don't specify a
// host name, then a name is generated automatically.
// Optional
Hostname string `json:"hostname"`
// Name of imagelist to be launched.
// Optional
ImageList string `json:"imagelist"`
// A label assigned by the user, specifically for defining inter-instance relationships.
// Optional
Label string `json:"label"`
// Name of this instance, generated by the server.
// Optional
Name string `json:"name"`
// Networking information.
// Optional
Networking map[string]NetworkingInfo `json:"networking"`
// If set to true (default), then reverse DNS records are created.
// If set to false, no reverse DNS records are created.
// Optional
ReverseDNS bool `json:"reverse_dns,omitempty"`
// Type of instance, as defined on site configuration.
// Required
Shape string `json:"shape"`
// A list of the Storage Attachments you want to associate with the instance.
// Optional
Storage []StorageAttachmentInput `json:"storage_attachments"`
// A list of the SSH public keys that you want to associate with the instance.
// Optional
SSHKeys []string `json:"sshkeys"`
// A list of tags to be supplied to the instance
// Optional
Tags []string `json:"tags"`
}
type StorageAttachmentInput struct {
// The index number for the volume. The allowed range is 1 to 10.
// If you want to use a storage volume as the boot disk for an instance, you must specify the index number for that volume as 1.
// The index determines the device name by which the volume is exposed to the instance.
Index int `json:"index"`
// The three-part name (/Compute-identity_domain/user/object) of the storage volume that you want to attach to the instance.
// Note that volumes attached to an instance at launch time can't be detached.
Volume string `json:"volume"`
}
const ReservationPrefix = "ipreservation"
const ReservationIPPrefix = "network/v1/ipreservation"
type NICModel string
const (
NICDefaultModel NICModel = "e1000"
)
// Struct of Networking info from a populated instance, or to be used as input to create an instance
type NetworkingInfo struct {
// The DNS name for the Shared network (Required)
// DNS A Record for an IP Network (Optional)
DNS []string `json:"dns,omitempty"`
// IP Network only.
// If you want to associate a static private IP Address,
// specify that here within the range of the supplied IPNetwork attribute.
// Optional
IPAddress string `json:"ip,omitempty"`
// IP Network only.
// The name of the IP Network you want to add the instance to.
// Required
IPNetwork string `json:"ipnetwork,omitempty"`
// IP Network only.
// The hexadecimal MAC Address of the interface
// Optional
MACAddress string `json:"address,omitempty"`
// Shared Network only.
// The type of NIC used. Must be set to 'e1000'
// Required
Model NICModel `json:"model,omitempty"`
// IP Network and Shared Network
// The name servers that are sent through DHCP as option 6.
// You can specify a maximum of eight name server IP addresses per interface.
// Optional
NameServers []string `json:"name_servers,omitempty"`
// The names of an IP Reservation to associate in an IP Network (Optional)
// Indicates whether a temporary or permanent public IP Address should be assigned
// in a Shared Network (Required)
Nat []string `json:"nat,omitempty"`
// IP Network and Shared Network
// The search domains that should be sent through DHCP as option 119.
// You can enter a maximum of eight search domain zones per interface.
// Optional
SearchDomains []string `json:"search_domains,omitempty"`
// Shared Network only.
// The security lists that you want to add the instance to
// Required
SecLists []string `json:"seclists,omitempty"`
// IP Network Only
// The name of the vNIC
// Optional
Vnic string `json:"vnic,omitempty"`
// IP Network only.
// The names of the vNICSets you want to add the interface to.
// Optional
VnicSets []string `json:"vnicsets,omitempty"`
}
// LaunchPlan defines a launch plan, used to launch instances with the supplied InstanceSpec(s)
type LaunchPlanInput struct {
// Describes an array of instances which should be launched
Instances []CreateInstanceInput `json:"instances"`
}
type LaunchPlanResponse struct {
// An array of instances which have been launched
Instances []InstanceInfo `json:"instances"`
}
// LaunchInstance creates and submits a LaunchPlan to launch a new instance.
func (c *InstancesClient) CreateInstance(input *CreateInstanceInput) (*InstanceInfo, error) {
qualifiedSSHKeys := []string{}
for _, key := range input.SSHKeys {
qualifiedSSHKeys = append(qualifiedSSHKeys, c.getQualifiedName(key))
}
input.SSHKeys = qualifiedSSHKeys
qualifiedStorageAttachments := []StorageAttachmentInput{}
for _, attachment := range input.Storage {
qualifiedStorageAttachments = append(qualifiedStorageAttachments, StorageAttachmentInput{
Index: attachment.Index,
Volume: c.getQualifiedName(attachment.Volume),
})
}
input.Storage = qualifiedStorageAttachments
input.Networking = c.qualifyNetworking(input.Networking)
input.Name = fmt.Sprintf(CMP_QUALIFIED_NAME, c.getUserName(), input.Name)
plan := LaunchPlanInput{Instances: []CreateInstanceInput{*input}}
var responseBody LaunchPlanResponse
if err := c.createResource(&plan, &responseBody); err != nil {
return nil, err
}
if len(responseBody.Instances) == 0 {
return nil, fmt.Errorf("No instance information returned: %#v", responseBody)
}
// Call wait for instance ready now, as creating the instance is an eventually consistent operation
getInput := &GetInstanceInput{
Name: input.Name,
ID: responseBody.Instances[0].ID,
}
// Wait for instance to be ready and return the result
// Don't have to unqualify any objects, as the GetInstance method will handle that
return c.WaitForInstanceRunning(getInput, WaitForInstanceReadyTimeout)
}
// Both of these fields are required. If they're not provided, things go wrong in
// incredibly amazing ways.
type GetInstanceInput struct {
// The Unqualified Name of this Instance
Name string
// The Unqualified ID of this Instance
ID string
}
func (g *GetInstanceInput) String() string {
return fmt.Sprintf(CMP_QUALIFIED_NAME, g.Name, g.ID)
}
// GetInstance retrieves information about an instance.
func (c *InstancesClient) GetInstance(input *GetInstanceInput) (*InstanceInfo, error) {
if input.ID == "" || input.Name == "" {
return nil, errors.New("Both instance name and ID need to be specified")
}
var responseBody InstanceInfo
if err := c.getResource(input.String(), &responseBody); err != nil {
return nil, err
}
if responseBody.Name == "" {
return nil, fmt.Errorf("Empty response body when requesting instance %s", input.Name)
}
// The returned 'Name' attribute is the fully qualified instance name + "/" + ID
// Split these out to accurately populate the fields
nID := strings.Split(c.getUnqualifiedName(responseBody.Name), "/")
responseBody.Name = nID[0]
responseBody.ID = nID[1]
c.unqualify(&responseBody.VCableID)
// Unqualify SSH Key names
sshKeyNames := []string{}
for _, sshKeyRef := range responseBody.SSHKeys {
sshKeyNames = append(sshKeyNames, c.getUnqualifiedName(sshKeyRef))
}
responseBody.SSHKeys = sshKeyNames
responseBody.Networking = c.unqualifyNetworking(responseBody.Networking)
responseBody.Storage = c.unqualifyStorage(responseBody.Storage)
return &responseBody, nil
}
type DeleteInstanceInput struct {
// The Unqualified Name of this Instance
Name string
// The Unqualified ID of this Instance
ID string
}
func (d *DeleteInstanceInput) String() string {
return fmt.Sprintf(CMP_QUALIFIED_NAME, d.Name, d.ID)
}
// DeleteInstance deletes an instance.
func (c *InstancesClient) DeleteInstance(input *DeleteInstanceInput) error {
// Call to delete the instance
if err := c.deleteResource(input.String()); err != nil {
return err
}
// Wait for instance to be deleted
return c.WaitForInstanceDeleted(input, WaitForInstanceDeleteTimeout)
}
// WaitForInstanceRunning waits for an instance to be completely initialized and available.
func (c *InstancesClient) WaitForInstanceRunning(input *GetInstanceInput, timeoutSeconds int) (*InstanceInfo, error) {
var info *InstanceInfo
var getErr error
err := c.waitFor("instance to be ready", timeoutSeconds, func() (bool, error) {
info, getErr = c.GetInstance(input)
if getErr != nil {
return false, getErr
}
switch s := info.State; s {
case InstanceError:
return false, fmt.Errorf("Error initializing instance: %s", info.ErrorReason)
case InstanceRunning:
c.debugLogString("Instance Running")
return true, nil
case InstanceQueued:
c.debugLogString("Instance Queuing")
return false, nil
case InstanceInitializing:
c.debugLogString("Instance Initializing")
return false, nil
case InstancePreparing:
c.debugLogString("Instance Preparing")
return false, nil
default:
c.debugLogString(fmt.Sprintf("Unknown instance state: %s, waiting", s))
return false, nil
}
})
return info, err
}
// WaitForInstanceDeleted waits for an instance to be fully deleted.
func (c *InstancesClient) WaitForInstanceDeleted(input *DeleteInstanceInput, timeoutSeconds int) error {
return c.waitFor("instance to be deleted", timeoutSeconds, func() (bool, error) {
var info InstanceInfo
if err := c.getResource(input.String(), &info); err != nil {
if WasNotFoundError(err) {
// Instance could not be found, thus deleted
return true, nil
}
// Some other error occurred trying to get instance, exit
return false, err
}
switch s := info.State; s {
case InstanceError:
return false, fmt.Errorf("Error stopping instance: %s", info.ErrorReason)
case InstanceStopping:
c.debugLogString("Instance stopping")
return false, nil
default:
c.debugLogString(fmt.Sprintf("Unknown instance state: %s, waiting", s))
return false, nil
}
})
}
func (c *InstancesClient) qualifyNetworking(info map[string]NetworkingInfo) map[string]NetworkingInfo {
qualifiedNetworks := map[string]NetworkingInfo{}
for k, v := range info {
qfd := v
sharedNetwork := false
if v.IPNetwork != "" {
// Network interface is for an IP Network
qfd.IPNetwork = c.getQualifiedName(v.IPNetwork)
sharedNetwork = true
}
if v.Vnic != "" {
qfd.Vnic = c.getQualifiedName(v.Vnic)
}
if v.Nat != nil {
qfd.Nat = c.qualifyNat(v.Nat, sharedNetwork)
}
if v.VnicSets != nil {
qfd.VnicSets = c.getQualifiedList(v.VnicSets)
}
if v.SecLists != nil {
// Network interface is for the shared network
secLists := []string{}
for _, v := range v.SecLists {
secLists = append(secLists, c.getQualifiedName(v))
}
qfd.SecLists = secLists
}
qualifiedNetworks[k] = qfd
}
return qualifiedNetworks
}
func (c *InstancesClient) unqualifyNetworking(info map[string]NetworkingInfo) map[string]NetworkingInfo {
// Unqualify ip network
unqualifiedNetworks := map[string]NetworkingInfo{}
for k, v := range info {
unq := v
if v.IPNetwork != "" {
unq.IPNetwork = c.getUnqualifiedName(v.IPNetwork)
}
if v.Vnic != "" {
unq.Vnic = c.getUnqualifiedName(v.Vnic)
}
if v.Nat != nil {
unq.Nat = c.unqualifyNat(v.Nat)
}
if v.VnicSets != nil {
unq.VnicSets = c.getUnqualifiedList(v.VnicSets)
}
if v.SecLists != nil {
secLists := []string{}
for _, v := range v.SecLists {
secLists = append(secLists, c.getUnqualifiedName(v))
}
v.SecLists = secLists
}
unqualifiedNetworks[k] = unq
}
return unqualifiedNetworks
}
func (c *InstancesClient) qualifyNat(nat []string, shared bool) []string {
qualifiedNats := []string{}
for _, v := range nat {
if strings.HasPrefix(v, "ippool:/oracle") {
qualifiedNats = append(qualifiedNats, v)
continue
}
prefix := ReservationPrefix
if shared {
prefix = ReservationIPPrefix
}
qualifiedNats = append(qualifiedNats, fmt.Sprintf("%s:%s", prefix, c.getQualifiedName(v)))
}
return qualifiedNats
}
func (c *InstancesClient) unqualifyNat(nat []string) []string {
unQualifiedNats := []string{}
for _, v := range nat {
if strings.HasPrefix(v, "ippool:/oracle") {
unQualifiedNats = append(unQualifiedNats, v)
continue
}
n := strings.Split(v, ":")
u := n[1]
unQualifiedNats = append(unQualifiedNats, c.getUnqualifiedName(u))
}
return unQualifiedNats
}
func (c *InstancesClient) unqualifyStorage(attachments []StorageAttachment) []StorageAttachment {
unqAttachments := []StorageAttachment{}
for _, v := range attachments {
if v.StorageVolumeName != "" {
v.StorageVolumeName = c.getUnqualifiedName(v.StorageVolumeName)
}
unqAttachments = append(unqAttachments, v)
}
return unqAttachments
}

View File

@ -0,0 +1,152 @@
package compute
const (
IPAddressAssociationDescription = "ip address association"
IPAddressAssociationContainerPath = "/network/v1/ipassociation/"
IPAddressAssociationResourcePath = "/network/v1/ipassociation"
)
type IPAddressAssociationsClient struct {
ResourceClient
}
// IPAddressAssociations() returns an IPAddressAssociationsClient that can be used to access the
// necessary CRUD functions for IP Address Associations.
func (c *Client) IPAddressAssociations() *IPAddressAssociationsClient {
return &IPAddressAssociationsClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: IPAddressAssociationDescription,
ContainerPath: IPAddressAssociationContainerPath,
ResourceRootPath: IPAddressAssociationResourcePath,
},
}
}
// IPAddressAssociationInfo contains the exported fields necessary to hold all the information about an
// IP Address Association
type IPAddressAssociationInfo struct {
// The name of the NAT IP address reservation.
IPAddressReservation string `json:"ipAddressReservation"`
// Name of the virtual NIC associated with this NAT IP reservation.
Vnic string `json:"vnic"`
// The name of the IP Address Association
Name string `json:"name"`
// Description of the IP Address Association
Description string `json:"description"`
// Slice of tags associated with the IP Address Association
Tags []string `json:"tags"`
// Uniform Resource Identifier for the IP Address Association
Uri string `json:"uri"`
}
type CreateIPAddressAssociationInput struct {
// The name of the IP Address Association to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// The name of the NAT IP address reservation.
// Optional
IPAddressReservation string `json:"ipAddressReservation,omitempty"`
// Name of the virtual NIC associated with this NAT IP reservation.
// Optional
Vnic string `json:"vnic,omitempty"`
// Description of the IPAddressAssociation
// Optional
Description string `json:"description"`
// String slice of tags to apply to the IP Address Association object
// Optional
Tags []string `json:"tags"`
}
// Create a new IP Address Association from an IPAddressAssociationsClient and an input struct.
// Returns a populated Info struct for the IP Address Association, and any errors
func (c *IPAddressAssociationsClient) CreateIPAddressAssociation(input *CreateIPAddressAssociationInput) (*IPAddressAssociationInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.IPAddressReservation = c.getQualifiedName(input.IPAddressReservation)
input.Vnic = c.getQualifiedName(input.Vnic)
var ipInfo IPAddressAssociationInfo
if err := c.createResource(&input, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type GetIPAddressAssociationInput struct {
// The name of the IP Address Association to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// Returns a populated IPAddressAssociationInfo struct from an input struct
func (c *IPAddressAssociationsClient) GetIPAddressAssociation(input *GetIPAddressAssociationInput) (*IPAddressAssociationInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPAddressAssociationInfo
if err := c.getResource(input.Name, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
// UpdateIPAddressAssociationInput defines what to update in a ip address association
type UpdateIPAddressAssociationInput struct {
// The name of the IP Address Association to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// The name of the NAT IP address reservation.
// Optional
IPAddressReservation string `json:"ipAddressReservation,omitempty"`
// Name of the virtual NIC associated with this NAT IP reservation.
// Optional
Vnic string `json:"vnic,omitempty"`
// Description of the IPAddressAssociation
// Optional
Description string `json:"description"`
// String slice of tags to apply to the IP Address Association object
// Optional
Tags []string `json:"tags"`
}
// UpdateIPAddressAssociation update the ip address association
func (c *IPAddressAssociationsClient) UpdateIPAddressAssociation(updateInput *UpdateIPAddressAssociationInput) (*IPAddressAssociationInfo, error) {
updateInput.Name = c.getQualifiedName(updateInput.Name)
updateInput.IPAddressReservation = c.getQualifiedName(updateInput.IPAddressReservation)
updateInput.Vnic = c.getQualifiedName(updateInput.Vnic)
var ipInfo IPAddressAssociationInfo
if err := c.updateResource(updateInput.Name, updateInput, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type DeleteIPAddressAssociationInput struct {
// The name of the IP Address Association to query for. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *IPAddressAssociationsClient) DeleteIPAddressAssociation(input *DeleteIPAddressAssociationInput) error {
return c.deleteResource(input.Name)
}
// Unqualifies any qualified fields in the IPAddressAssociationInfo struct
func (c *IPAddressAssociationsClient) success(info *IPAddressAssociationInfo) (*IPAddressAssociationInfo, error) {
c.unqualify(&info.Name)
c.unqualify(&info.Vnic)
c.unqualify(&info.IPAddressReservation)
return info, nil
}

View File

@ -0,0 +1,135 @@
package compute
const (
IPAddressPrefixSetDescription = "ip address prefix set"
IPAddressPrefixSetContainerPath = "/network/v1/ipaddressprefixset/"
IPAddressPrefixSetResourcePath = "/network/v1/ipaddressprefixset"
)
type IPAddressPrefixSetsClient struct {
ResourceClient
}
// IPAddressPrefixSets() returns an IPAddressPrefixSetsClient that can be used to access the
// necessary CRUD functions for IP Address Prefix Sets.
func (c *Client) IPAddressPrefixSets() *IPAddressPrefixSetsClient {
return &IPAddressPrefixSetsClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: IPAddressPrefixSetDescription,
ContainerPath: IPAddressPrefixSetContainerPath,
ResourceRootPath: IPAddressPrefixSetResourcePath,
},
}
}
// IPAddressPrefixSetInfo contains the exported fields necessary to hold all the information about an
// IP Address Prefix Set
type IPAddressPrefixSetInfo struct {
// The name of the IP Address Prefix Set
Name string `json:"name"`
// Description of the IP Address Prefix Set
Description string `json:"description"`
// List of CIDR IPv4 prefixes assigned in the virtual network.
IPAddressPrefixes []string `json:"ipAddressPrefixes"`
// Slice of tags associated with the IP Address Prefix Set
Tags []string `json:"tags"`
// Uniform Resource Identifier for the IP Address Prefix Set
Uri string `json:"uri"`
}
type CreateIPAddressPrefixSetInput struct {
// The name of the IP Address Prefix Set to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Description of the IPAddressPrefixSet
// Optional
Description string `json:"description"`
// List of CIDR IPv4 prefixes assigned in the virtual network.
// Optional
IPAddressPrefixes []string `json:"ipAddressPrefixes"`
// String slice of tags to apply to the IP Address Prefix Set object
// Optional
Tags []string `json:"tags"`
}
// Create a new IP Address Prefix Set from an IPAddressPrefixSetsClient and an input struct.
// Returns a populated Info struct for the IP Address Prefix Set, and any errors
func (c *IPAddressPrefixSetsClient) CreateIPAddressPrefixSet(input *CreateIPAddressPrefixSetInput) (*IPAddressPrefixSetInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPAddressPrefixSetInfo
if err := c.createResource(&input, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type GetIPAddressPrefixSetInput struct {
// The name of the IP Address Prefix Set to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// Returns a populated IPAddressPrefixSetInfo struct from an input struct
func (c *IPAddressPrefixSetsClient) GetIPAddressPrefixSet(input *GetIPAddressPrefixSetInput) (*IPAddressPrefixSetInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPAddressPrefixSetInfo
if err := c.getResource(input.Name, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
// UpdateIPAddressPrefixSetInput defines what to update in a ip address prefix set
type UpdateIPAddressPrefixSetInput struct {
// The name of the IP Address Prefix Set to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Description of the IPAddressPrefixSet
// Optional
Description string `json:"description"`
// List of CIDR IPv4 prefixes assigned in the virtual network.
IPAddressPrefixes []string `json:"ipAddressPrefixes"`
// String slice of tags to apply to the IP Address Prefix Set object
// Optional
Tags []string `json:"tags"`
}
// UpdateIPAddressPrefixSet update the ip address prefix set
func (c *IPAddressPrefixSetsClient) UpdateIPAddressPrefixSet(updateInput *UpdateIPAddressPrefixSetInput) (*IPAddressPrefixSetInfo, error) {
updateInput.Name = c.getQualifiedName(updateInput.Name)
var ipInfo IPAddressPrefixSetInfo
if err := c.updateResource(updateInput.Name, updateInput, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type DeleteIPAddressPrefixSetInput struct {
// The name of the IP Address Prefix Set to query for. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *IPAddressPrefixSetsClient) DeleteIPAddressPrefixSet(input *DeleteIPAddressPrefixSetInput) error {
return c.deleteResource(input.Name)
}
// Unqualifies any qualified fields in the IPAddressPrefixSetInfo struct
func (c *IPAddressPrefixSetsClient) success(info *IPAddressPrefixSetInfo) (*IPAddressPrefixSetInfo, error) {
c.unqualify(&info.Name)
return info, nil
}

View File

@ -0,0 +1,190 @@
package compute
import (
"fmt"
"path/filepath"
)
// IPAddressReservationsClient is a client to manage ip address reservation resources
type IPAddressReservationsClient struct {
*ResourceClient
}
const (
IPAddressReservationDescription = "IP Address Reservation"
IPAddressReservationContainerPath = "/network/v1/ipreservation/"
IPAddressReservationResourcePath = "/network/v1/ipreservation"
IPAddressReservationQualifier = "/oracle/public"
)
// IPAddressReservations returns an IPAddressReservationsClient to manage IP address reservation
// resources
func (c *Client) IPAddressReservations() *IPAddressReservationsClient {
return &IPAddressReservationsClient{
ResourceClient: &ResourceClient{
Client: c,
ResourceDescription: IPAddressReservationDescription,
ContainerPath: IPAddressReservationContainerPath,
ResourceRootPath: IPAddressReservationResourcePath,
},
}
}
// IPAddressReservation describes an IP Address reservation
type IPAddressReservation struct {
// Description of the IP Address Reservation
Description string `json:"description"`
// Reserved NAT IPv4 address from the IP Address Pool
IPAddress string `json:"ipAddress"`
// Name of the IP Address pool to reserve the NAT IP from
IPAddressPool string `json:"ipAddressPool"`
// Name of the reservation
Name string `json:"name"`
// Tags associated with the object
Tags []string `json:"tags"`
// Uniform Resource Identified for the reservation
Uri string `json:"uri"`
}
const (
PublicIPAddressPool = "public-ippool"
PrivateIPAddressPool = "cloud-ippool"
)
// CreateIPAddressReservationInput defines input parameters to create an ip address reservation
type CreateIPAddressReservationInput struct {
// Description of the IP Address Reservation
// Optional
Description string `json:"description"`
// IP Address pool from which to reserve an IP Address.
// Can be one of the following:
//
// 'public-ippool' - When you attach an IP Address from this pool to an instance, you enable
// access between the public Internet and the instance
// 'cloud-ippool' - When you attach an IP Address from this pool to an instance, the instance
// can communicate privately with other Oracle Cloud Services
// Optional
IPAddressPool string `json:"ipAddressPool"`
// The name of the reservation to create
// Required
Name string `json:"name"`
// Tags to associate with the IP Reservation
// Optional
Tags []string `json:"tags"`
}
// Takes an input struct, creates an IP Address reservation, and returns the info struct and any errors
func (c *IPAddressReservationsClient) CreateIPAddressReservation(input *CreateIPAddressReservationInput) (*IPAddressReservation, error) {
var ipAddrRes IPAddressReservation
// Qualify supplied name
input.Name = c.getQualifiedName(input.Name)
// Qualify supplied address pool if not nil
if input.IPAddressPool != "" {
input.IPAddressPool = c.qualifyIPAddressPool(input.IPAddressPool)
}
if err := c.createResource(input, &ipAddrRes); err != nil {
return nil, err
}
return c.success(&ipAddrRes)
}
// Parameters to retrieve information on an ip address reservation
type GetIPAddressReservationInput struct {
// Name of the IP Reservation
// Required
Name string `json:"name"`
}
// Returns an IP Address Reservation and any errors
func (c *IPAddressReservationsClient) GetIPAddressReservation(input *GetIPAddressReservationInput) (*IPAddressReservation, error) {
var ipAddrRes IPAddressReservation
input.Name = c.getQualifiedName(input.Name)
if err := c.getResource(input.Name, &ipAddrRes); err != nil {
return nil, err
}
return c.success(&ipAddrRes)
}
// Parameters to update an IP Address reservation
type UpdateIPAddressReservationInput struct {
// Description of the IP Address Reservation
// Optional
Description string `json:"description"`
// IP Address pool from which to reserve an IP Address.
// Can be one of the following:
//
// 'public-ippool' - When you attach an IP Address from this pool to an instance, you enable
// access between the public Internet and the instance
// 'cloud-ippool' - When you attach an IP Address from this pool to an instance, the instance
// can communicate privately with other Oracle Cloud Services
// Optional
IPAddressPool string `json:"ipAddressPool"`
// The name of the reservation to create
// Required
Name string `json:"name"`
// Tags to associate with the IP Reservation
// Optional
Tags []string `json:"tags"`
}
func (c *IPAddressReservationsClient) UpdateIPAddressReservation(input *UpdateIPAddressReservationInput) (*IPAddressReservation, error) {
var ipAddrRes IPAddressReservation
// Qualify supplied name
input.Name = c.getQualifiedName(input.Name)
// Qualify supplied address pool if not nil
if input.IPAddressPool != "" {
input.IPAddressPool = c.qualifyIPAddressPool(input.IPAddressPool)
}
if err := c.updateResource(input.Name, input, &ipAddrRes); err != nil {
return nil, err
}
return c.success(&ipAddrRes)
}
// Parameters to delete an IP Address Reservation
type DeleteIPAddressReservationInput struct {
// The name of the reservation to delete
Name string `json:"name"`
}
func (c *IPAddressReservationsClient) DeleteIPAddressReservation(input *DeleteIPAddressReservationInput) error {
input.Name = c.getQualifiedName(input.Name)
return c.deleteResource(input.Name)
}
func (c *IPAddressReservationsClient) success(result *IPAddressReservation) (*IPAddressReservation, error) {
c.unqualify(&result.Name)
if result.IPAddressPool != "" {
result.IPAddressPool = c.unqualifyIPAddressPool(result.IPAddressPool)
}
return result, nil
}
func (c *IPAddressReservationsClient) qualifyIPAddressPool(input string) string {
// Add '/oracle/public/'
return fmt.Sprintf("%s/%s", IPAddressReservationQualifier, input)
}
func (c *IPAddressReservationsClient) unqualifyIPAddressPool(input string) string {
// Remove '/oracle/public/'
return filepath.Base(input)
}

View File

@ -0,0 +1,118 @@
package compute
import (
"fmt"
"strings"
)
// IPAssociationsClient is a client for the IP Association functions of the Compute API.
type IPAssociationsClient struct {
*ResourceClient
}
// IPAssociations obtains a IPAssociationsClient which can be used to access to the
// IP Association functions of the Compute API
func (c *Client) IPAssociations() *IPAssociationsClient {
return &IPAssociationsClient{
ResourceClient: &ResourceClient{
Client: c,
ResourceDescription: "ip association",
ContainerPath: "/ip/association/",
ResourceRootPath: "/ip/association",
}}
}
// IPAssociationInfo describes an existing IP association.
type IPAssociationInfo struct {
// TODO: it'd probably make sense to expose the `ip` field here too?
// The three-part name of the object (/Compute-identity_domain/user/object).
Name string `json:"name"`
// The three-part name of the IP reservation object in the format (/Compute-identity_domain/user/object).
// An IP reservation is a public IP address which is attached to an Oracle Compute Cloud Service instance that requires access to or from the Internet.
Reservation string `json:"reservation"`
// The type of IP Address to associate with this instance
// for a Dynamic IP address specify `ippool:/oracle/public/ippool`.
// for a Static IP address specify the three part name of the existing IP reservation
ParentPool string `json:"parentpool"`
// Uniform Resource Identifier for the IP Association
URI string `json:"uri"`
// The three-part name of a vcable ID of an instance that is associated with the IP reservation.
VCable string `json:"vcable"`
}
type CreateIPAssociationInput struct {
// The type of IP Address to associate with this instance
// for a Dynamic IP address specify `ippool:/oracle/public/ippool`.
// for a Static IP address specify the three part name of the existing IP reservation
// Required
ParentPool string `json:"parentpool"`
// The three-part name of the vcable ID of the instance that you want to associate with an IP address. The three-part name is in the format: /Compute-identity_domain/user/object.
// Required
VCable string `json:"vcable"`
}
// CreateIPAssociation creates a new IP association with the supplied vcable and parentpool.
func (c *IPAssociationsClient) CreateIPAssociation(input *CreateIPAssociationInput) (*IPAssociationInfo, error) {
input.VCable = c.getQualifiedName(input.VCable)
input.ParentPool = c.getQualifiedParentPoolName(input.ParentPool)
var assocInfo IPAssociationInfo
if err := c.createResource(input, &assocInfo); err != nil {
return nil, err
}
return c.success(&assocInfo)
}
type GetIPAssociationInput struct {
// The three-part name of the IP Association
// Required.
Name string `json:"name"`
}
// GetIPAssociation retrieves the IP association with the given name.
func (c *IPAssociationsClient) GetIPAssociation(input *GetIPAssociationInput) (*IPAssociationInfo, error) {
var assocInfo IPAssociationInfo
if err := c.getResource(input.Name, &assocInfo); err != nil {
return nil, err
}
return c.success(&assocInfo)
}
type DeleteIPAssociationInput struct {
// The three-part name of the IP Association
// Required.
Name string `json:"name"`
}
// DeleteIPAssociation deletes the IP association with the given name.
func (c *IPAssociationsClient) DeleteIPAssociation(input *DeleteIPAssociationInput) error {
return c.deleteResource(input.Name)
}
func (c *IPAssociationsClient) getQualifiedParentPoolName(parentpool string) string {
parts := strings.Split(parentpool, ":")
pooltype := parts[0]
name := parts[1]
return fmt.Sprintf("%s:%s", pooltype, c.getQualifiedName(name))
}
func (c *IPAssociationsClient) unqualifyParentPoolName(parentpool *string) {
parts := strings.Split(*parentpool, ":")
pooltype := parts[0]
name := parts[1]
*parentpool = fmt.Sprintf("%s:%s", pooltype, c.getUnqualifiedName(name))
}
// Unqualifies identifiers
func (c *IPAssociationsClient) success(assocInfo *IPAssociationInfo) (*IPAssociationInfo, error) {
c.unqualify(&assocInfo.Name, &assocInfo.VCable)
c.unqualifyParentPoolName(&assocInfo.ParentPool)
return assocInfo, nil
}

View File

@ -0,0 +1,99 @@
package compute
const (
IPNetworkExchangeDescription = "ip network exchange"
IPNetworkExchangeContainerPath = "/network/v1/ipnetworkexchange/"
IPNetworkExchangeResourcePath = "/network/v1/ipnetworkexchange"
)
type IPNetworkExchangesClient struct {
ResourceClient
}
// IPNetworkExchanges() returns an IPNetworkExchangesClient that can be used to access the
// necessary CRUD functions for IP Network Exchanges.
func (c *Client) IPNetworkExchanges() *IPNetworkExchangesClient {
return &IPNetworkExchangesClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: IPNetworkExchangeDescription,
ContainerPath: IPNetworkExchangeContainerPath,
ResourceRootPath: IPNetworkExchangeResourcePath,
},
}
}
// IPNetworkExchangeInfo contains the exported fields necessary to hold all the information about an
// IP Network Exchange
type IPNetworkExchangeInfo struct {
// The name of the IP Network Exchange
Name string `json:"name"`
// Description of the IP Network Exchange
Description string `json:"description"`
// Slice of tags associated with the IP Network Exchange
Tags []string `json:"tags"`
// Uniform Resource Identifier for the IP Network Exchange
Uri string `json:"uri"`
}
type CreateIPNetworkExchangeInput struct {
// The name of the IP Network Exchange to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Description of the IPNetworkExchange
// Optional
Description string `json:"description"`
// String slice of tags to apply to the IP Network Exchange object
// Optional
Tags []string `json:"tags"`
}
// Create a new IP Network Exchange from an IPNetworkExchangesClient and an input struct.
// Returns a populated Info struct for the IP Network Exchange, and any errors
func (c *IPNetworkExchangesClient) CreateIPNetworkExchange(input *CreateIPNetworkExchangeInput) (*IPNetworkExchangeInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPNetworkExchangeInfo
if err := c.createResource(&input, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type GetIPNetworkExchangeInput struct {
// The name of the IP Network Exchange to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// Returns a populated IPNetworkExchangeInfo struct from an input struct
func (c *IPNetworkExchangesClient) GetIPNetworkExchange(input *GetIPNetworkExchangeInput) (*IPNetworkExchangeInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPNetworkExchangeInfo
if err := c.getResource(input.Name, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type DeleteIPNetworkExchangeInput struct {
// The name of the IP Network Exchange to query for. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *IPNetworkExchangesClient) DeleteIPNetworkExchange(input *DeleteIPNetworkExchangeInput) error {
return c.deleteResource(input.Name)
}
// Unqualifies any qualified fields in the IPNetworkExchangeInfo struct
func (c *IPNetworkExchangesClient) success(info *IPNetworkExchangeInfo) (*IPNetworkExchangeInfo, error) {
c.unqualify(&info.Name)
return info, nil
}

View File

@ -0,0 +1,186 @@
package compute
const (
IPNetworkDescription = "ip network"
IPNetworkContainerPath = "/network/v1/ipnetwork/"
IPNetworkResourcePath = "/network/v1/ipnetwork"
)
type IPNetworksClient struct {
ResourceClient
}
// IPNetworks() returns an IPNetworksClient that can be used to access the
// necessary CRUD functions for IP Networks.
func (c *Client) IPNetworks() *IPNetworksClient {
return &IPNetworksClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: IPNetworkDescription,
ContainerPath: IPNetworkContainerPath,
ResourceRootPath: IPNetworkResourcePath,
},
}
}
// IPNetworkInfo contains the exported fields necessary to hold all the information about an
// IP Network
type IPNetworkInfo struct {
// The name of the IP Network
Name string `json:"name"`
// The CIDR IPv4 prefix associated with the IP Network
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the IP Network Exchange associated with the IP Network
IPNetworkExchange string `json:"ipNetworkExchange,omitempty"`
// Description of the IP Network
Description string `json:"description"`
// Whether public internet access was enabled using NAPT for VNICs without any public IP reservation
PublicNaptEnabled bool `json:"publicNaptEnabledFlag"`
// Slice of tags associated with the IP Network
Tags []string `json:"tags"`
// Uniform Resource Identifier for the IP Network
Uri string `json:"uri"`
}
type CreateIPNetworkInput struct {
// The name of the IP Network to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Specify the size of the IP Subnet. It is a range of IPv4 addresses assigned in the virtual
// network, in CIDR address prefix format.
// While specifying the IP address prefix take care of the following points:
//
//* These IP addresses aren't part of the common pool of Oracle-provided IP addresses used by the shared network.
//
//* There's no conflict with the range of IP addresses used in another IP network, the IP addresses used your on-premises network, or with the range of private IP addresses used in the shared network. If IP networks with overlapping IP subnets are linked to an IP exchange, packets going to and from those IP networks are dropped.
//
//* The upper limit of the CIDR block size for an IP network is /16.
//
//Note: The first IP address of any IP network is reserved for the default gateway, the DHCP server, and the DNS server of that IP network.
// Required
IPAddressPrefix string `json:"ipAddressPrefix"`
//Specify the IP network exchange to which the IP network belongs.
//You can add an IP network to only one IP network exchange, but an IP network exchange
//can include multiple IP networks. An IP network exchange enables access between IP networks
//that have non-overlapping addresses, so that instances on these networks can exchange packets
//with each other without NAT.
// Optional
IPNetworkExchange string `json:"ipNetworkExchange,omitempty"`
// Description of the IPNetwork
// Optional
Description string `json:"description"`
// Enable public internet access using NAPT for VNICs without any public IP reservation
// Optional
PublicNaptEnabled bool `json:"publicNaptEnabledFlag"`
// String slice of tags to apply to the IP Network object
// Optional
Tags []string `json:"tags"`
}
// Create a new IP Network from an IPNetworksClient and an input struct.
// Returns a populated Info struct for the IP Network, and any errors
func (c *IPNetworksClient) CreateIPNetwork(input *CreateIPNetworkInput) (*IPNetworkInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.IPNetworkExchange = c.getQualifiedName(input.IPNetworkExchange)
var ipInfo IPNetworkInfo
if err := c.createResource(&input, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type GetIPNetworkInput struct {
// The name of the IP Network to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// Returns a populated IPNetworkInfo struct from an input struct
func (c *IPNetworksClient) GetIPNetwork(input *GetIPNetworkInput) (*IPNetworkInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo IPNetworkInfo
if err := c.getResource(input.Name, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type UpdateIPNetworkInput struct {
// The name of the IP Network to update. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// Specify the size of the IP Subnet. It is a range of IPv4 addresses assigned in the virtual
// network, in CIDR address prefix format.
// While specifying the IP address prefix take care of the following points:
//
//* These IP addresses aren't part of the common pool of Oracle-provided IP addresses used by the shared network.
//
//* There's no conflict with the range of IP addresses used in another IP network, the IP addresses used your on-premises network, or with the range of private IP addresses used in the shared network. If IP networks with overlapping IP subnets are linked to an IP exchange, packets going to and from those IP networks are dropped.
//
//* The upper limit of the CIDR block size for an IP network is /16.
//
//Note: The first IP address of any IP network is reserved for the default gateway, the DHCP server, and the DNS server of that IP network.
// Required
IPAddressPrefix string `json:"ipAddressPrefix"`
//Specify the IP network exchange to which the IP network belongs.
//You can add an IP network to only one IP network exchange, but an IP network exchange
//can include multiple IP networks. An IP network exchange enables access between IP networks
//that have non-overlapping addresses, so that instances on these networks can exchange packets
//with each other without NAT.
// Optional
IPNetworkExchange string `json:"ipNetworkExchange,omitempty"`
// Description of the IPNetwork
// Optional
Description string `json:"description"`
// Enable public internet access using NAPT for VNICs without any public IP reservation
// Optional
PublicNaptEnabled bool `json:"publicNaptEnabledFlag"`
// String slice of tags to apply to the IP Network object
// Optional
Tags []string `json:"tags"`
}
func (c *IPNetworksClient) UpdateIPNetwork(input *UpdateIPNetworkInput) (*IPNetworkInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.IPNetworkExchange = c.getQualifiedName(input.IPNetworkExchange)
var ipInfo IPNetworkInfo
if err := c.updateResource(input.Name, &input, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
type DeleteIPNetworkInput struct {
// The name of the IP Network to query for. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *IPNetworksClient) DeleteIPNetwork(input *DeleteIPNetworkInput) error {
return c.deleteResource(input.Name)
}
// Unqualifies any qualified fields in the IPNetworkInfo struct
func (c *IPNetworksClient) success(info *IPNetworkInfo) (*IPNetworkInfo, error) {
c.unqualify(&info.Name)
c.unqualify(&info.IPNetworkExchange)
return info, nil
}

View File

@ -0,0 +1,147 @@
package compute
// IPReservationsClient is a client for the IP Reservations functions of the Compute API.
type IPReservationsClient struct {
*ResourceClient
}
const (
IPReservationDesc = "ip reservation"
IPReservationContainerPath = "/ip/reservation/"
IPReservataionResourcePath = "/ip/reservation"
)
// IPReservations obtains an IPReservationsClient which can be used to access to the
// IP Reservations functions of the Compute API
func (c *Client) IPReservations() *IPReservationsClient {
return &IPReservationsClient{
ResourceClient: &ResourceClient{
Client: c,
ResourceDescription: IPReservationDesc,
ContainerPath: IPReservationContainerPath,
ResourceRootPath: IPReservataionResourcePath,
}}
}
type IPReservationPool string
const (
PublicReservationPool IPReservationPool = "/oracle/public/ippool"
)
// IPReservationInput describes an existing IP reservation.
type IPReservation struct {
// Shows the default account for your identity domain.
Account string `json:"account"`
// Public IP address.
IP string `json:"ip"`
// The three-part name of the IP Reservation (/Compute-identity_domain/user/object).
Name string `json:"name"`
// Pool of public IP addresses
ParentPool IPReservationPool `json:"parentpool"`
// Is the IP Reservation Persistent (i.e. static) or not (i.e. Dynamic)?
Permanent bool `json:"permanent"`
// A comma-separated list of strings which helps you to identify IP reservation.
Tags []string `json:"tags"`
// Uniform Resource Identifier
Uri string `json:"uri"`
// Is the IP reservation associated with an instance?
Used bool `json:"used"`
}
// CreateIPReservationInput defines an IP reservation to be created.
type CreateIPReservationInput struct {
// The name of the object
// If you don't specify a name for this object, then the name is generated automatically.
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods.
// Object names are case-sensitive.
// Optional
Name string `json:"name"`
// Pool of public IP addresses. This must be set to `ippool`
// Required
ParentPool IPReservationPool `json:"parentpool"`
// Is the IP Reservation Persistent (i.e. static) or not (i.e. Dynamic)?
// Required
Permanent bool `json:"permanent"`
// A comma-separated list of strings which helps you to identify IP reservations.
// Optional
Tags []string `json:"tags"`
}
// CreateIPReservation creates a new IP reservation with the given parentpool, tags and permanent flag.
func (c *IPReservationsClient) CreateIPReservation(input *CreateIPReservationInput) (*IPReservation, error) {
var ipInput IPReservation
input.Name = c.getQualifiedName(input.Name)
if err := c.createResource(input, &ipInput); err != nil {
return nil, err
}
return c.success(&ipInput)
}
// GetIPReservationInput defines an IP Reservation to get
type GetIPReservationInput struct {
// The name of the IP Reservation
// Required
Name string
}
// GetIPReservation retrieves the IP reservation with the given name.
func (c *IPReservationsClient) GetIPReservation(input *GetIPReservationInput) (*IPReservation, error) {
var ipInput IPReservation
input.Name = c.getQualifiedName(input.Name)
if err := c.getResource(input.Name, &ipInput); err != nil {
return nil, err
}
return c.success(&ipInput)
}
// UpdateIPReservationInput defines an IP Reservation to be updated
type UpdateIPReservationInput struct {
// The name of the object
// If you don't specify a name for this object, then the name is generated automatically.
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods.
// Object names are case-sensitive.
// Required
Name string `json:"name"`
// Pool of public IP addresses.
// Required
ParentPool IPReservationPool `json:"parentpool"`
// Is the IP Reservation Persistent (i.e. static) or not (i.e. Dynamic)?
// Required
Permanent bool `json:"permanent"`
// A comma-separated list of strings which helps you to identify IP reservations.
// Optional
Tags []string `json:"tags"`
}
// UpdateIPReservation updates the IP reservation.
func (c *IPReservationsClient) UpdateIPReservation(input *UpdateIPReservationInput) (*IPReservation, error) {
var updateOutput IPReservation
input.Name = c.getQualifiedName(input.Name)
if err := c.updateResource(input.Name, input, &updateOutput); err != nil {
return nil, err
}
return c.success(&updateOutput)
}
// DeleteIPReservationInput defines an IP Reservation to delete
type DeleteIPReservationInput struct {
// The name of the IP Reservation
// Required
Name string
}
// DeleteIPReservation deletes the IP reservation with the given name.
func (c *IPReservationsClient) DeleteIPReservation(input *DeleteIPReservationInput) error {
input.Name = c.getQualifiedName(input.Name)
return c.deleteResource(input.Name)
}
func (c *IPReservationsClient) success(result *IPReservation) (*IPReservation, error) {
c.unqualify(&result.Name)
return result, nil
}

View File

@ -0,0 +1,28 @@
package compute
import (
"bytes"
"fmt"
"net/http"
"github.com/hashicorp/go-oracle-terraform/opc"
)
// Log a string if debug logs are on
func (c *Client) debugLogString(str string) {
if c.loglevel != opc.LogDebug {
return
}
c.logger.Log(str)
}
func (c *Client) debugLogReq(req *http.Request) {
// Don't need to log this if not debugging
if c.loglevel != opc.LogDebug {
return
}
buf := new(bytes.Buffer)
buf.ReadFrom(req.Body)
c.logger.Log(fmt.Sprintf("DEBUG: HTTP %s Req %s: %s",
req.Method, req.URL.String(), buf.String()))
}

View File

@ -0,0 +1,94 @@
package compute
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"github.com/mitchellh/mapstructure"
)
// ResourceClient is an AuthenticatedClient with some additional information about the resources to be addressed.
type ResourceClient struct {
*Client
ResourceDescription string
ContainerPath string
ResourceRootPath string
}
func (c *ResourceClient) createResource(requestBody interface{}, responseBody interface{}) error {
resp, err := c.executeRequest("POST", c.ContainerPath, requestBody)
if err != nil {
return err
}
return c.unmarshalResponseBody(resp, responseBody)
}
func (c *ResourceClient) updateResource(name string, requestBody interface{}, responseBody interface{}) error {
resp, err := c.executeRequest("PUT", c.getObjectPath(c.ResourceRootPath, name), requestBody)
if err != nil {
return err
}
return c.unmarshalResponseBody(resp, responseBody)
}
func (c *ResourceClient) getResource(name string, responseBody interface{}) error {
var objectPath string
if name != "" {
objectPath = c.getObjectPath(c.ResourceRootPath, name)
} else {
objectPath = c.ResourceRootPath
}
resp, err := c.executeRequest("GET", objectPath, nil)
if err != nil {
return err
}
return c.unmarshalResponseBody(resp, responseBody)
}
func (c *ResourceClient) deleteResource(name string) error {
var objectPath string
if name != "" {
objectPath = c.getObjectPath(c.ResourceRootPath, name)
} else {
objectPath = c.ResourceRootPath
}
_, err := c.executeRequest("DELETE", objectPath, nil)
if err != nil {
return err
}
// No errors and no response body to write
return nil
}
func (c *ResourceClient) unmarshalResponseBody(resp *http.Response, iface interface{}) error {
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
c.debugLogString(fmt.Sprintf("HTTP Resp (%d): %s", resp.StatusCode, buf.String()))
// JSON decode response into interface
var tmp interface{}
dcd := json.NewDecoder(buf)
if err := dcd.Decode(&tmp); err != nil {
return err
}
// Use mapstructure to weakly decode into the resulting interface
msdcd, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
WeaklyTypedInput: true,
Result: iface,
TagName: "json",
})
if err != nil {
return err
}
if err := msdcd.Decode(tmp); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,153 @@
package compute
const (
RoutesDescription = "IP Network Route"
RoutesContainerPath = "/network/v1/route/"
RoutesResourcePath = "/network/v1/route"
)
type RoutesClient struct {
ResourceClient
}
func (c *Client) Routes() *RoutesClient {
return &RoutesClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: RoutesDescription,
ContainerPath: RoutesContainerPath,
ResourceRootPath: RoutesResourcePath,
},
}
}
type RouteInfo struct {
// Admin distance associated with this route
AdminDistance int `json:"adminDistance"`
// Description of the route
Description string `json:"description"`
// CIDR IPv4 Prefix associated with this route
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the route
Name string `json:"name"`
// Name of the VNIC set associated with the route
NextHopVnicSet string `json:"nextHopVnicSet"`
// Slice of Tags associated with the route
Tags []string `json:"tags,omitempty"`
// Uniform resource identifier associated with the route
Uri string `json:"uri"`
}
type CreateRouteInput struct {
// Specify 0,1, or 2 as the route's administrative distance.
// If you do not specify a value, the default value is 0.
// The same prefix can be used in multiple routes. In this case, packets are routed over all the matching
// routes with the lowest administrative distance.
// In the case multiple routes with the same lowest administrative distance match,
// routing occurs over all these routes using ECMP.
// Optional
AdminDistance int `json:"adminDistance"`
// Description of the route
// Optional
Description string `json:"description"`
// The IPv4 address prefix in CIDR format, of the external network (external to the vNIC set)
// from which you want to route traffic
// Required
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the route.
// Names can only contain alphanumeric, underscore, dash, and period characters. Case-sensitive
// Required
Name string `json:"name"`
// Name of the virtual NIC set to route matching packets to.
// Routed flows are load-balanced among all the virtual NICs in the virtual NIC set
// Required
NextHopVnicSet string `json:"nextHopVnicSet"`
// Slice of tags to be associated with the route
// Optional
Tags []string `json:"tags,omitempty"`
}
func (c *RoutesClient) CreateRoute(input *CreateRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.NextHopVnicSet = c.getQualifiedName(input.NextHopVnicSet)
var routeInfo RouteInfo
if err := c.createResource(&input, &routeInfo); err != nil {
return nil, err
}
return c.success(&routeInfo)
}
type GetRouteInput struct {
// Name of the Route to query for. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *RoutesClient) GetRoute(input *GetRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var routeInfo RouteInfo
if err := c.getResource(input.Name, &routeInfo); err != nil {
return nil, err
}
return c.success(&routeInfo)
}
type UpdateRouteInput struct {
// Specify 0,1, or 2 as the route's administrative distance.
// If you do not specify a value, the default value is 0.
// The same prefix can be used in multiple routes. In this case, packets are routed over all the matching
// routes with the lowest administrative distance.
// In the case multiple routes with the same lowest administrative distance match,
// routing occurs over all these routes using ECMP.
// Optional
AdminDistance int `json:"adminDistance"`
// Description of the route
// Optional
Description string `json:"description"`
// The IPv4 address prefix in CIDR format, of the external network (external to the vNIC set)
// from which you want to route traffic
// Required
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the route.
// Names can only contain alphanumeric, underscore, dash, and period characters. Case-sensitive
// Required
Name string `json:"name"`
// Name of the virtual NIC set to route matching packets to.
// Routed flows are load-balanced among all the virtual NICs in the virtual NIC set
// Required
NextHopVnicSet string `json:"nextHopVnicSet"`
// Slice of tags to be associated with the route
// Optional
Tags []string `json:"tags"`
}
func (c *RoutesClient) UpdateRoute(input *UpdateRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.NextHopVnicSet = c.getQualifiedName(input.NextHopVnicSet)
var routeInfo RouteInfo
if err := c.updateResource(input.Name, &input, &routeInfo); err != nil {
return nil, err
}
return c.success(&routeInfo)
}
type DeleteRouteInput struct {
// Name of the Route to delete. Case-sensitive
// Required
Name string `json:"name"`
}
func (c *RoutesClient) DeleteRoute(input *DeleteRouteInput) error {
return c.deleteResource(input.Name)
}
func (c *RoutesClient) success(info *RouteInfo) (*RouteInfo, error) {
c.unqualify(&info.Name)
c.unqualify(&info.NextHopVnicSet)
return info, nil
}

View File

@ -0,0 +1,193 @@
package compute
// SecRulesClient is a client for the Sec Rules functions of the Compute API.
type SecRulesClient struct {
ResourceClient
}
// SecRules obtains a SecRulesClient which can be used to access to the
// Sec Rules functions of the Compute API
func (c *Client) SecRules() *SecRulesClient {
return &SecRulesClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: "security ip list",
ContainerPath: "/secrule/",
ResourceRootPath: "/secrule",
}}
}
// SecRuleInfo describes an existing sec rule.
type SecRuleInfo struct {
// Set this parameter to PERMIT.
Action string `json:"action"`
// The name of the security application
Application string `json:"application"`
// A description of the sec rule
Description string `json:"description"`
// Indicates whether the security rule is enabled
Disabled bool `json:"disabled"`
// The name of the destination security list or security IP list.
DestinationList string `json:"dst_list"`
// The name of the sec rule
Name string `json:"name"`
// The name of the source security list or security IP list.
SourceList string `json:"src_list"`
// Uniform Resource Identifier for the sec rule
URI string `json:"uri"`
}
// CreateSecRuleInput defines a sec rule to be created.
type CreateSecRuleInput struct {
// Set this parameter to PERMIT.
// Required
Action string `json:"action"`
// The name of the security application for user-defined or predefined security applications.
// Required
Application string `json:"application"`
// Description of the IP Network
// Optional
Description string `json:"description"`
// Indicates whether the sec rule is enabled (set to false) or disabled (true).
// The default setting is false.
// Optional
Disabled bool `json:"disabled"`
// The name of the destination security list or security IP list.
//
// You must use the prefix seclist: or seciplist: to identify the list type.
//
// You can specify a security IP list as the destination in a secrule,
// provided src_list is a security list that has DENY as its outbound policy.
//
// You cannot specify any of the security IP lists in the /oracle/public container
// as a destination in a secrule.
// Required
DestinationList string `json:"dst_list"`
// The name of the Sec Rule to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// The name of the source security list or security IP list.
//
// You must use the prefix seclist: or seciplist: to identify the list type.
//
// Required
SourceList string `json:"src_list"`
}
// CreateSecRule creates a new sec rule.
func (c *SecRulesClient) CreateSecRule(createInput *CreateSecRuleInput) (*SecRuleInfo, error) {
createInput.Name = c.getQualifiedName(createInput.Name)
createInput.SourceList = c.getQualifiedListName(createInput.SourceList)
createInput.DestinationList = c.getQualifiedListName(createInput.DestinationList)
createInput.Application = c.getQualifiedName(createInput.Application)
var ruleInfo SecRuleInfo
if err := c.createResource(createInput, &ruleInfo); err != nil {
return nil, err
}
return c.success(&ruleInfo)
}
// GetSecRuleInput describes the Sec Rule to get
type GetSecRuleInput struct {
// The name of the Sec Rule to query for
// Required
Name string `json:"name"`
}
// GetSecRule retrieves the sec rule with the given name.
func (c *SecRulesClient) GetSecRule(getInput *GetSecRuleInput) (*SecRuleInfo, error) {
var ruleInfo SecRuleInfo
if err := c.getResource(getInput.Name, &ruleInfo); err != nil {
return nil, err
}
return c.success(&ruleInfo)
}
// UpdateSecRuleInput describes a secruity rule to update
type UpdateSecRuleInput struct {
// Set this parameter to PERMIT.
// Required
Action string `json:"action"`
// The name of the security application for user-defined or predefined security applications.
// Required
Application string `json:"application"`
// Description of the IP Network
// Optional
Description string `json:"description"`
// Indicates whether the sec rule is enabled (set to false) or disabled (true).
// The default setting is false.
// Optional
Disabled bool `json:"disabled"`
// The name of the destination security list or security IP list.
//
// You must use the prefix seclist: or seciplist: to identify the list type.
//
// You can specify a security IP list as the destination in a secrule,
// provided src_list is a security list that has DENY as its outbound policy.
//
// You cannot specify any of the security IP lists in the /oracle/public container
// as a destination in a secrule.
// Required
DestinationList string `json:"dst_list"`
// The name of the Sec Rule to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// The name of the source security list or security IP list.
//
// You must use the prefix seclist: or seciplist: to identify the list type.
//
// Required
SourceList string `json:"src_list"`
}
// UpdateSecRule modifies the properties of the sec rule with the given name.
func (c *SecRulesClient) UpdateSecRule(updateInput *UpdateSecRuleInput) (*SecRuleInfo, error) {
updateInput.Name = c.getQualifiedName(updateInput.Name)
updateInput.SourceList = c.getQualifiedListName(updateInput.SourceList)
updateInput.DestinationList = c.getQualifiedListName(updateInput.DestinationList)
updateInput.Application = c.getQualifiedName(updateInput.Application)
var ruleInfo SecRuleInfo
if err := c.updateResource(updateInput.Name, updateInput, &ruleInfo); err != nil {
return nil, err
}
return c.success(&ruleInfo)
}
// DeleteSecRuleInput describes the sec rule to delete
type DeleteSecRuleInput struct {
// The name of the Sec Rule to delete.
// Required
Name string `json:"name"`
}
// DeleteSecRule deletes the sec rule with the given name.
func (c *SecRulesClient) DeleteSecRule(deleteInput *DeleteSecRuleInput) error {
return c.deleteResource(deleteInput.Name)
}
func (c *SecRulesClient) success(ruleInfo *SecRuleInfo) (*SecRuleInfo, error) {
ruleInfo.Name = c.getUnqualifiedName(ruleInfo.Name)
ruleInfo.SourceList = c.unqualifyListName(ruleInfo.SourceList)
ruleInfo.DestinationList = c.unqualifyListName(ruleInfo.DestinationList)
ruleInfo.Application = c.getUnqualifiedName(ruleInfo.Application)
return ruleInfo, nil
}

View File

@ -0,0 +1,150 @@
package compute
// SecurityApplicationsClient is a client for the Security Application functions of the Compute API.
type SecurityApplicationsClient struct {
ResourceClient
}
// SecurityApplications obtains a SecurityApplicationsClient which can be used to access to the
// Security Application functions of the Compute API
func (c *Client) SecurityApplications() *SecurityApplicationsClient {
return &SecurityApplicationsClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: "security application",
ContainerPath: "/secapplication/",
ResourceRootPath: "/secapplication",
}}
}
// SecurityApplicationInfo describes an existing security application.
type SecurityApplicationInfo struct {
// A description of the security application.
Description string `json:"description"`
// The TCP or UDP destination port number. This can be a port range, such as 5900-5999 for TCP.
DPort string `json:"dport"`
// The ICMP code.
ICMPCode SecurityApplicationICMPCode `json:"icmpcode"`
// The ICMP type.
ICMPType SecurityApplicationICMPType `json:"icmptype"`
// The three-part name of the Security Application (/Compute-identity_domain/user/object).
Name string `json:"name"`
// The protocol to use.
Protocol SecurityApplicationProtocol `json:"protocol"`
// The Uniform Resource Identifier
URI string `json:"uri"`
}
type SecurityApplicationProtocol string
const (
All SecurityApplicationProtocol = "all"
AH SecurityApplicationProtocol = "ah"
ESP SecurityApplicationProtocol = "esp"
ICMP SecurityApplicationProtocol = "icmp"
ICMPV6 SecurityApplicationProtocol = "icmpv6"
IGMP SecurityApplicationProtocol = "igmp"
IPIP SecurityApplicationProtocol = "ipip"
GRE SecurityApplicationProtocol = "gre"
MPLSIP SecurityApplicationProtocol = "mplsip"
OSPF SecurityApplicationProtocol = "ospf"
PIM SecurityApplicationProtocol = "pim"
RDP SecurityApplicationProtocol = "rdp"
SCTP SecurityApplicationProtocol = "sctp"
TCP SecurityApplicationProtocol = "tcp"
UDP SecurityApplicationProtocol = "udp"
)
type SecurityApplicationICMPCode string
const (
Admin SecurityApplicationICMPCode = "admin"
Df SecurityApplicationICMPCode = "df"
Host SecurityApplicationICMPCode = "host"
Network SecurityApplicationICMPCode = "network"
Port SecurityApplicationICMPCode = "port"
Protocol SecurityApplicationICMPCode = "protocol"
)
type SecurityApplicationICMPType string
const (
Echo SecurityApplicationICMPType = "echo"
Reply SecurityApplicationICMPType = "reply"
TTL SecurityApplicationICMPType = "ttl"
TraceRoute SecurityApplicationICMPType = "traceroute"
Unreachable SecurityApplicationICMPType = "unreachable"
)
func (c *SecurityApplicationsClient) success(result *SecurityApplicationInfo) (*SecurityApplicationInfo, error) {
c.unqualify(&result.Name)
return result, nil
}
// CreateSecurityApplicationInput describes the Security Application to create
type CreateSecurityApplicationInput struct {
// A description of the security application.
// Optional
Description string `json:"description"`
// The TCP or UDP destination port number.
// You can also specify a port range, such as 5900-5999 for TCP.
// This parameter isn't relevant to the icmp protocol.
// Required if the Protocol is TCP or UDP
DPort string `json:"dport"`
// The ICMP code. This parameter is relevant only if you specify ICMP as the protocol.
// If you specify icmp as the protocol and don't specify icmptype or icmpcode, then all ICMP packets are matched.
// Optional
ICMPCode SecurityApplicationICMPCode `json:"icmpcode,omitempty"`
// This parameter is relevant only if you specify ICMP as the protocol.
// If you specify icmp as the protocol and don't specify icmptype or icmpcode, then all ICMP packets are matched.
// Optional
ICMPType SecurityApplicationICMPType `json:"icmptype,omitempty"`
// The three-part name of the Security Application (/Compute-identity_domain/user/object).
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods. Object names are case-sensitive.
// Required
Name string `json:"name"`
// The protocol to use.
// Required
Protocol SecurityApplicationProtocol `json:"protocol"`
}
// CreateSecurityApplication creates a new security application.
func (c *SecurityApplicationsClient) CreateSecurityApplication(input *CreateSecurityApplicationInput) (*SecurityApplicationInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var appInfo SecurityApplicationInfo
if err := c.createResource(&input, &appInfo); err != nil {
return nil, err
}
return c.success(&appInfo)
}
// GetSecurityApplicationInput describes the Security Application to obtain
type GetSecurityApplicationInput struct {
// The three-part name of the Security Application (/Compute-identity_domain/user/object).
// Required
Name string `json:"name"`
}
// GetSecurityApplication retrieves the security application with the given name.
func (c *SecurityApplicationsClient) GetSecurityApplication(input *GetSecurityApplicationInput) (*SecurityApplicationInfo, error) {
var appInfo SecurityApplicationInfo
if err := c.getResource(input.Name, &appInfo); err != nil {
return nil, err
}
return c.success(&appInfo)
}
// DeleteSecurityApplicationInput describes the Security Application to delete
type DeleteSecurityApplicationInput struct {
// The three-part name of the Security Application (/Compute-identity_domain/user/object).
// Required
Name string `json:"name"`
}
// DeleteSecurityApplication deletes the security application with the given name.
func (c *SecurityApplicationsClient) DeleteSecurityApplication(input *DeleteSecurityApplicationInput) error {
return c.deleteResource(input.Name)
}

View File

@ -0,0 +1,95 @@
package compute
// SecurityAssociationsClient is a client for the Security Association functions of the Compute API.
type SecurityAssociationsClient struct {
ResourceClient
}
// SecurityAssociations obtains a SecurityAssociationsClient which can be used to access to the
// Security Association functions of the Compute API
func (c *Client) SecurityAssociations() *SecurityAssociationsClient {
return &SecurityAssociationsClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: "security association",
ContainerPath: "/secassociation/",
ResourceRootPath: "/secassociation",
}}
}
// SecurityAssociationInfo describes an existing security association.
type SecurityAssociationInfo struct {
// The three-part name of the Security Association (/Compute-identity_domain/user/object).
Name string `json:"name"`
// The name of the Security List that you want to associate with the instance.
SecList string `json:"seclist"`
// vCable of the instance that you want to associate with the security list.
VCable string `json:"vcable"`
// Uniform Resource Identifier
URI string `json:"uri"`
}
// CreateSecurityAssociationInput defines a security association to be created.
type CreateSecurityAssociationInput struct {
// The three-part name of the Security Association (/Compute-identity_domain/user/object).
// If you don't specify a name for this object, then the name is generated automatically.
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods. Object names are case-sensitive.
// Optional
Name string `json:"name"`
// The name of the Security list that you want to associate with the instance.
// Required
SecList string `json:"seclist"`
// The name of the vCable of the instance that you want to associate with the security list.
// Required
VCable string `json:"vcable"`
}
// CreateSecurityAssociation creates a security association between the given VCable and security list.
func (c *SecurityAssociationsClient) CreateSecurityAssociation(createInput *CreateSecurityAssociationInput) (*SecurityAssociationInfo, error) {
if createInput.Name != "" {
createInput.Name = c.getQualifiedName(createInput.Name)
}
createInput.VCable = c.getQualifiedName(createInput.VCable)
createInput.SecList = c.getQualifiedName(createInput.SecList)
var assocInfo SecurityAssociationInfo
if err := c.createResource(&createInput, &assocInfo); err != nil {
return nil, err
}
return c.success(&assocInfo)
}
// GetSecurityAssociationInput describes the security association to get
type GetSecurityAssociationInput struct {
// The three-part name of the Security Association (/Compute-identity_domain/user/object).
// Required
Name string `json:"name"`
}
// GetSecurityAssociation retrieves the security association with the given name.
func (c *SecurityAssociationsClient) GetSecurityAssociation(getInput *GetSecurityAssociationInput) (*SecurityAssociationInfo, error) {
var assocInfo SecurityAssociationInfo
if err := c.getResource(getInput.Name, &assocInfo); err != nil {
return nil, err
}
return c.success(&assocInfo)
}
// DeleteSecurityAssociationInput describes the security association to delete
type DeleteSecurityAssociationInput struct {
// The three-part name of the Security Association (/Compute-identity_domain/user/object).
// Required
Name string `json:"name"`
}
// DeleteSecurityAssociation deletes the security association with the given name.
func (c *SecurityAssociationsClient) DeleteSecurityAssociation(deleteInput *DeleteSecurityAssociationInput) error {
return c.deleteResource(deleteInput.Name)
}
func (c *SecurityAssociationsClient) success(assocInfo *SecurityAssociationInfo) (*SecurityAssociationInfo, error) {
c.unqualify(&assocInfo.Name, &assocInfo.SecList, &assocInfo.VCable)
return assocInfo, nil
}

Some files were not shown because too many files have changed in this diff Show More