Merge pull request #5819 from hashicorp/oracle-oci-builder
Oracle oci builder
This commit is contained in:
commit
caea770af1
|
@ -71,11 +71,16 @@ func TestBuilderPrepare_ChrootMounts(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_ChrootMountsBadDefaults(t *testing.T) {
|
||||
b := &Builder{}
|
||||
config := testConfig()
|
||||
|
||||
config["chroot_mounts"] = [][]string{
|
||||
{"bad"},
|
||||
}
|
||||
warnings, err = b.Prepare(config)
|
||||
warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
|
@ -135,9 +140,14 @@ func TestBuilderPrepare_CopyFiles(t *testing.T) {
|
|||
if len(b.config.CopyFiles) != 1 && b.config.CopyFiles[0] != "/etc/resolv.conf" {
|
||||
t.Errorf("Was expecting default value for copy_files.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_CopyFilesNoDefault(t *testing.T) {
|
||||
b := &Builder{}
|
||||
config := testConfig()
|
||||
|
||||
config["copy_files"] = []string{}
|
||||
warnings, err = b.Prepare(config)
|
||||
warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
)
|
||||
|
||||
// Artifact is an artifact implementation that contains Image List
|
||||
// and Machine Image info.
|
||||
type Artifact struct {
|
||||
MachineImageName string
|
||||
MachineImageFile string
|
||||
ImageListVersion int
|
||||
driver *compute.ComputeClient
|
||||
}
|
||||
|
||||
// BuilderId uniquely identifies the builder.
|
||||
func (a *Artifact) BuilderId() string {
|
||||
return BuilderId
|
||||
}
|
||||
|
||||
// Files lists the files associated with an artifact. We don't have any files
|
||||
// as the custom image is stored server side.
|
||||
func (a *Artifact) Files() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return a.MachineImageName
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return fmt.Sprintf("An image list entry was created: \n"+
|
||||
"Name: %s\n"+
|
||||
"File: %s\n"+
|
||||
"Version: %d",
|
||||
a.MachineImageName, a.MachineImageFile, a.ImageListVersion)
|
||||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Destroy deletes the custom image associated with the artifact.
|
||||
func (a *Artifact) Destroy() error {
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/go-oracle-terraform/opc"
|
||||
ocommon "github.com/hashicorp/packer/builder/oracle/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// BuilderId uniquely identifies the builder
|
||||
const BuilderId = "packer.oracle.classic"
|
||||
|
||||
// Builder is a builder implementation that creates Oracle OCI custom images.
|
||||
type Builder struct {
|
||||
config *Config
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
func (b *Builder) Prepare(rawConfig ...interface{}) ([]string, error) {
|
||||
config, err := NewConfig(rawConfig...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.config = config
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||
loggingEnabled := os.Getenv("PACKER_OCI_CLASSIC_LOGGING") != ""
|
||||
httpClient := cleanhttp.DefaultClient()
|
||||
config := &opc.Config{
|
||||
Username: opc.String(b.config.Username),
|
||||
Password: opc.String(b.config.Password),
|
||||
IdentityDomain: opc.String(b.config.IdentityDomain),
|
||||
APIEndpoint: b.config.apiEndpointURL,
|
||||
LogLevel: opc.LogDebug,
|
||||
Logger: &Logger{loggingEnabled},
|
||||
// Logger: # Leave blank to use the default logger, or provide your own
|
||||
HTTPClient: httpClient,
|
||||
}
|
||||
// Create the Compute Client
|
||||
client, err := compute.NewComputeClient(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error creating OPC Compute Client: %s", err)
|
||||
}
|
||||
|
||||
// Populate the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("client", client)
|
||||
|
||||
// Build the steps
|
||||
steps := []multistep.Step{
|
||||
&ocommon.StepKeyPair{
|
||||
Debug: b.config.PackerDebug,
|
||||
DebugKeyPath: fmt.Sprintf("oci_classic_%s.pem", b.config.PackerBuildName),
|
||||
PrivateKeyFile: b.config.Comm.SSHPrivateKey,
|
||||
},
|
||||
&stepCreateIPReservation{},
|
||||
&stepAddKeysToAPI{},
|
||||
&stepSecurity{},
|
||||
&stepCreateInstance{},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: ocommon.CommHost,
|
||||
SSHConfig: ocommon.SSHConfig(
|
||||
b.config.Comm.SSHUsername,
|
||||
b.config.Comm.SSHPassword),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
&stepSnapshot{},
|
||||
&stepListImages{},
|
||||
}
|
||||
|
||||
// Run the steps
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(state)
|
||||
|
||||
// If there was an error, return that
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
// If there is no snapshot, then just return
|
||||
if _, ok := state.GetOk("snapshot"); !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Build the artifact and return it
|
||||
artifact := &Artifact{
|
||||
ImageListVersion: state.Get("image_list_version").(int),
|
||||
MachineImageName: state.Get("machine_image_name").(string),
|
||||
MachineImageFile: state.Get("machine_image_file").(string),
|
||||
driver: client,
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
// Cancel terminates a running build.
|
||||
func (b *Builder) Cancel() {
|
||||
if b.runner != nil {
|
||||
log.Println("Cancelling the step runner...")
|
||||
b.runner.Cancel()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
// Access config overrides
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
IdentityDomain string `mapstructure:"identity_domain"`
|
||||
APIEndpoint string `mapstructure:"api_endpoint"`
|
||||
apiEndpointURL *url.URL
|
||||
|
||||
// Image
|
||||
ImageName string `mapstructure:"image_name"`
|
||||
Shape string `mapstructure:"shape"`
|
||||
SourceImageList string `mapstructure:"source_image_list"`
|
||||
DestImageList string `mapstructure:"dest_image_list"`
|
||||
// Optional; if you don't enter anything, the image list description
|
||||
// will read "Packer-built image list"
|
||||
DestImageListDescription string `mapstructure:"image_description"`
|
||||
// Optional. Describes what computers are allowed to reach your instance
|
||||
// via SSH. This whitelist must contain the computer you're running Packer
|
||||
// from. It defaults to public-internet, meaning that you can SSH into your
|
||||
// instance from anywhere as long as you have the right keys
|
||||
SSHSourceList string `mapstructure:"ssh_source_list"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
func NewConfig(raws ...interface{}) (*Config, error) {
|
||||
c := &Config{}
|
||||
|
||||
// Decode from template
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &c.ctx,
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to mapstructure Config: %+v", err)
|
||||
}
|
||||
|
||||
c.apiEndpointURL, err = url.Parse(c.APIEndpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing API Endpoint: %s", err)
|
||||
}
|
||||
// Set default source list
|
||||
if c.SSHSourceList == "" {
|
||||
c.SSHSourceList = "seciplist:/oracle/public/public-internet"
|
||||
}
|
||||
// Use default oracle username with sudo privileges
|
||||
if c.Comm.SSHUsername == "" {
|
||||
c.Comm.SSHUsername = "opc"
|
||||
}
|
||||
|
||||
// Validate that all required fields are present
|
||||
var errs *packer.MultiError
|
||||
required := map[string]string{
|
||||
"username": c.Username,
|
||||
"password": c.Password,
|
||||
"api_endpoint": c.APIEndpoint,
|
||||
"identity_domain": c.IdentityDomain,
|
||||
"source_image_list": c.SourceImageList,
|
||||
"dest_image_list": c.DestImageList,
|
||||
"shape": c.Shape,
|
||||
}
|
||||
for k, v := range required {
|
||||
if v == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("You must specify a %s.", k))
|
||||
}
|
||||
}
|
||||
|
||||
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
|
||||
errs = packer.MultiErrorAppend(errs, es...)
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"identity_domain": "abc12345",
|
||||
"username": "test@hashicorp.com",
|
||||
"password": "testpassword123",
|
||||
"api_endpoint": "https://api-test.compute.test.oraclecloud.com/",
|
||||
"dest_image_list": "/Config-thing/myuser/myimage",
|
||||
"source_image_list": "/oracle/public/whatever",
|
||||
"shape": "oc3",
|
||||
"image_name": "TestImageName",
|
||||
"ssh_username": "opc",
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigAutoFillsSourceList(t *testing.T) {
|
||||
tc := testConfig()
|
||||
conf, err := NewConfig(tc)
|
||||
if err != nil {
|
||||
t.Fatalf("Should not have error: %s", err.Error())
|
||||
}
|
||||
if conf.SSHSourceList != "seciplist:/oracle/public/public-internet" {
|
||||
t.Fatalf("conf.SSHSourceList should have been "+
|
||||
"\"seciplist:/oracle/public/public-internet\" but is \"%s\"",
|
||||
conf.SSHSourceList)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidationCatchesMissing(t *testing.T) {
|
||||
required := []string{
|
||||
"username",
|
||||
"password",
|
||||
"api_endpoint",
|
||||
"identity_domain",
|
||||
"dest_image_list",
|
||||
"source_image_list",
|
||||
"shape",
|
||||
}
|
||||
for _, key := range required {
|
||||
tc := testConfig()
|
||||
delete(tc, key)
|
||||
_, err := NewConfig(tc)
|
||||
if err == nil {
|
||||
t.Fatalf("Test should have failed when config lacked %s!", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidationsIgnoresOptional(t *testing.T) {
|
||||
tc := testConfig()
|
||||
delete(tc, "ssh_username")
|
||||
_, err := NewConfig(tc)
|
||||
if err != nil {
|
||||
t.Fatalf("Shouldn't care if ssh_username is missing: err: %#v", err.Error())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package classic
|
||||
|
||||
import "log"
|
||||
|
||||
type Logger struct {
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
func (l *Logger) Log(input ...interface{}) {
|
||||
if !l.Enabled {
|
||||
return
|
||||
}
|
||||
log.Println(input...)
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepAddKeysToAPI struct{}
|
||||
|
||||
func (s *stepAddKeysToAPI) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
// get variables from state
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
|
||||
// grab packer-generated key from statebag context.
|
||||
sshPublicKey := strings.TrimSpace(state.Get("publicKey").(string))
|
||||
|
||||
// form API call to add key to compute cloud
|
||||
sshKeyName := fmt.Sprintf("/Compute-%s/%s/packer_generated_key_%s",
|
||||
config.IdentityDomain, config.Username, uuid.TimeOrderedUUID())
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating temporary key: %s", sshKeyName))
|
||||
|
||||
sshKeysClient := client.SSHKeys()
|
||||
sshKeysInput := compute.CreateSSHKeyInput{
|
||||
Name: sshKeyName,
|
||||
Key: sshPublicKey,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
// Load the packer-generated SSH key into the Oracle Compute cloud.
|
||||
keyInfo, err := sshKeysClient.CreateSSHKey(&sshKeysInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem adding Public SSH key through Oracle's API: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("key_name", keyInfo.Name)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepAddKeysToAPI) Cleanup(state multistep.StateBag) {
|
||||
// Delete the keys we created during this run
|
||||
keyName := state.Get("key_name").(string)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Deleting SSH keys...")
|
||||
deleteInput := compute.DeleteSSHKeyInput{Name: keyName}
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
deleteClient := client.SSHKeys()
|
||||
err := deleteClient.DeleteSSHKey(&deleteInput)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Error deleting SSH keys: %s", err.Error()))
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateInstance struct{}
|
||||
|
||||
func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
// get variables from state
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Creating Instance...")
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
keyName := state.Get("key_name").(string)
|
||||
ipAddName := state.Get("ipres_name").(string)
|
||||
secListName := state.Get("security_list").(string)
|
||||
|
||||
netInfo := compute.NetworkingInfo{
|
||||
Nat: []string{ipAddName},
|
||||
SecLists: []string{secListName},
|
||||
}
|
||||
|
||||
// get instances client
|
||||
instanceClient := client.Instances()
|
||||
|
||||
// Instances Input
|
||||
input := &compute.CreateInstanceInput{
|
||||
Name: config.ImageName,
|
||||
Shape: config.Shape,
|
||||
ImageList: config.SourceImageList,
|
||||
SSHKeys: []string{keyName},
|
||||
Networking: map[string]compute.NetworkingInfo{"eth0": netInfo},
|
||||
}
|
||||
|
||||
instanceInfo, err := instanceClient.CreateInstance(input)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem creating instance: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
state.Put("instance_id", instanceInfo.ID)
|
||||
ui.Message(fmt.Sprintf("Created instance: %s.", instanceInfo.ID))
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
||||
// terminate instance
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
config := state.Get("config").(*Config)
|
||||
imID := state.Get("instance_id").(string)
|
||||
|
||||
ui.Say("Terminating source instance...")
|
||||
|
||||
instanceClient := client.Instances()
|
||||
input := &compute.DeleteInstanceInput{
|
||||
Name: config.ImageName,
|
||||
ID: imID,
|
||||
}
|
||||
|
||||
err := instanceClient.DeleteInstance(input)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem destroying instance: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return
|
||||
}
|
||||
// TODO wait for instance state to change to deleted?
|
||||
ui.Say("Terminated instance.")
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateIPReservation struct{}
|
||||
|
||||
func (s *stepCreateIPReservation) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
iprClient := client.IPReservations()
|
||||
// TODO: add optional Name and Tags
|
||||
|
||||
ipresName := fmt.Sprintf("ipres_%s_%s", config.ImageName, uuid.TimeOrderedUUID())
|
||||
ui.Message(fmt.Sprintf("Creating temporary IP reservation: %s", ipresName))
|
||||
|
||||
IPInput := &compute.CreateIPReservationInput{
|
||||
ParentPool: compute.PublicReservationPool,
|
||||
Permanent: true,
|
||||
Name: ipresName,
|
||||
}
|
||||
ipRes, err := iprClient.CreateIPReservation(IPInput)
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error creating IP Reservation: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("instance_ip", ipRes.IP)
|
||||
state.Put("ipres_name", ipresName)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepCreateIPReservation) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Cleaning up IP reservations...")
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
|
||||
ipResName := state.Get("ipres_name").(string)
|
||||
input := compute.DeleteIPReservationInput{Name: ipResName}
|
||||
ipClient := client.IPReservations()
|
||||
err := ipClient.DeleteIPReservation(&input)
|
||||
if err != nil {
|
||||
fmt.Printf("error deleting IP reservation: %s", err.Error())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepListImages struct{}
|
||||
|
||||
func (s *stepListImages) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
// get variables from state
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
ui.Say("Adding image to image list...")
|
||||
|
||||
imageListClient := client.ImageList()
|
||||
getInput := compute.GetImageListInput{
|
||||
Name: config.DestImageList,
|
||||
}
|
||||
imList, err := imageListClient.GetImageList(&getInput)
|
||||
if err != nil {
|
||||
// If the list didn't exist, create it.
|
||||
ui.Say(fmt.Sprintf(err.Error()))
|
||||
ui.Say(fmt.Sprintf("Destination image list %s does not exist; Creating it...",
|
||||
config.DestImageList))
|
||||
|
||||
ilInput := compute.CreateImageListInput{
|
||||
Name: config.DestImageList,
|
||||
Description: "Packer-built image list",
|
||||
}
|
||||
|
||||
imList, err = imageListClient.CreateImageList(&ilInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem creating image list: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
ui.Message(fmt.Sprintf("Image list %s created!", imList.URI))
|
||||
}
|
||||
|
||||
// Now create and image list entry for the image into that list.
|
||||
snap := state.Get("snapshot").(*compute.Snapshot)
|
||||
version := len(imList.Entries) + 1
|
||||
entriesClient := client.ImageListEntries()
|
||||
entriesInput := compute.CreateImageListEntryInput{
|
||||
Name: config.DestImageList,
|
||||
MachineImages: []string{fmt.Sprintf("/Compute-%s/%s/%s",
|
||||
config.IdentityDomain, config.Username, snap.MachineImage)},
|
||||
Version: version,
|
||||
}
|
||||
entryInfo, err := entriesClient.CreateImageListEntry(&entriesInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem creating an image list entry: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("image_list_entry", entryInfo)
|
||||
ui.Message(fmt.Sprintf("created image list entry %s", entryInfo.Name))
|
||||
|
||||
machineImagesClient := client.MachineImages()
|
||||
getImagesInput := compute.GetMachineImageInput{
|
||||
Name: config.ImageName,
|
||||
}
|
||||
|
||||
// Update image list default to use latest version
|
||||
updateInput := compute.UpdateImageListInput{
|
||||
Default: version,
|
||||
Description: config.DestImageListDescription,
|
||||
Name: config.DestImageList,
|
||||
}
|
||||
_, err = imageListClient.UpdateImageList(&updateInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem updating default image list version: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Grab info about the machine image to return with the artifact
|
||||
imInfo, err := machineImagesClient.GetMachineImage(&getImagesInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem getting machine image info: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("machine_image_file", imInfo.File)
|
||||
state.Put("machine_image_name", imInfo.Name)
|
||||
state.Put("image_list_version", version)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepListImages) Cleanup(state multistep.StateBag) {
|
||||
// Nothing to do
|
||||
return
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepSecurity struct{}
|
||||
|
||||
func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Configuring security lists and rules to enable SSH access...")
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
|
||||
secListName := fmt.Sprintf("/Compute-%s/%s/Packer_SSH_Allow_%s",
|
||||
config.IdentityDomain, config.Username, config.ImageName)
|
||||
secListClient := client.SecurityLists()
|
||||
secListInput := compute.CreateSecurityListInput{
|
||||
Description: "Packer-generated security list to give packer ssh access",
|
||||
Name: secListName,
|
||||
}
|
||||
_, err := secListClient.CreateSecurityList(&secListInput)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
err = fmt.Errorf("Error creating security List to"+
|
||||
" allow Packer to connect to Oracle instance via SSH: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
// DOCS NOTE: user must have Compute_Operations role
|
||||
// Create security rule that allows Packer to connect via SSH
|
||||
secRulesClient := client.SecRules()
|
||||
secRulesInput := compute.CreateSecRuleInput{
|
||||
Action: "PERMIT",
|
||||
Application: "/oracle/public/ssh",
|
||||
Description: "Packer-generated security rule to allow ssh",
|
||||
DestinationList: fmt.Sprintf("seclist:%s", secListName),
|
||||
Name: fmt.Sprintf("Packer-allow-SSH-Rule_%s", config.ImageName),
|
||||
SourceList: config.SSHSourceList,
|
||||
}
|
||||
|
||||
secRuleName := fmt.Sprintf("/Compute-%s/%s/Packer-allow-SSH-Rule_%s",
|
||||
config.IdentityDomain, config.Username, config.ImageName)
|
||||
_, err = secRulesClient.CreateSecRule(&secRulesInput)
|
||||
if err != nil {
|
||||
log.Printf("Error creating security rule to allow SSH: %s", err.Error())
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
err = fmt.Errorf("Error creating security rule to"+
|
||||
" allow Packer to connect to Oracle instance via SSH: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
state.Put("security_rule_name", secRuleName)
|
||||
state.Put("security_list", secListName)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepSecurity) Cleanup(state multistep.StateBag) {
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Deleting temporary rules and lists...")
|
||||
|
||||
// delete security rules that Packer generated
|
||||
secRuleName := state.Get("security_rule_name").(string)
|
||||
secRulesClient := client.SecRules()
|
||||
ruleInput := compute.DeleteSecRuleInput{Name: secRuleName}
|
||||
err := secRulesClient.DeleteSecRule(&ruleInput)
|
||||
if err != nil {
|
||||
ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+
|
||||
"please delete manually. (error: %s)", secRuleName, err.Error()))
|
||||
}
|
||||
|
||||
// delete security list that Packer generated
|
||||
secListName := state.Get("security_list").(string)
|
||||
secListClient := client.SecurityLists()
|
||||
input := compute.DeleteSecurityListInput{Name: secListName}
|
||||
err = secListClient.DeleteSecurityList(&input)
|
||||
if err != nil {
|
||||
ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+
|
||||
"please delete manually. (error : %s)", secListName, err.Error()))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package classic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepSnapshot struct{}
|
||||
|
||||
func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
// get variables from state
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Creating Snapshot...")
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
instanceID := state.Get("instance_id").(string)
|
||||
|
||||
// get instances client
|
||||
snapshotClient := client.Snapshots()
|
||||
|
||||
// Instances Input
|
||||
snapshotInput := &compute.CreateSnapshotInput{
|
||||
Instance: fmt.Sprintf("%s/%s", config.ImageName, instanceID),
|
||||
MachineImage: config.ImageName,
|
||||
}
|
||||
|
||||
snap, err := snapshotClient.CreateSnapshot(snapshotInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem creating snapshot: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
state.Put("snapshot", snap)
|
||||
ui.Message(fmt.Sprintf("Created snapshot: %s.", snap.Name))
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
|
||||
// Delete the snapshot
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Deleting Snapshot...")
|
||||
client := state.Get("client").(*compute.ComputeClient)
|
||||
snap := state.Get("snapshot").(*compute.Snapshot)
|
||||
snapClient := client.Snapshots()
|
||||
snapInput := compute.DeleteSnapshotInput{
|
||||
Snapshot: snap.Name,
|
||||
MachineImage: snap.MachineImage,
|
||||
}
|
||||
|
||||
err := snapClient.DeleteSnapshotResourceOnly(&snapInput)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Problem deleting snapshot: %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package oci
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -8,7 +8,7 @@ import (
|
|||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func commHost(state multistep.StateBag) (string, error) {
|
||||
func CommHost(state multistep.StateBag) (string, error) {
|
||||
ipAddress := state.Get("instance_ip").(string)
|
||||
return ipAddress, nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package oci
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -16,13 +16,13 @@ import (
|
|||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type stepKeyPair struct {
|
||||
type StepKeyPair struct {
|
||||
Debug bool
|
||||
DebugKeyPath string
|
||||
PrivateKeyFile string
|
||||
}
|
||||
|
||||
func (s *stepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.PrivateKeyFile != "" {
|
||||
|
@ -112,6 +112,6 @@ func (s *stepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepKeyPair) Cleanup(state multistep.StateBag) {
|
||||
func (s *StepKeyPair) Cleanup(state multistep.StateBag) {
|
||||
// Nothing to do
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
ocommon "github.com/hashicorp/packer/builder/oracle/common"
|
||||
client "github.com/hashicorp/packer/builder/oracle/oci/client"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
|
@ -50,7 +51,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
|
||||
// Build the steps
|
||||
steps := []multistep.Step{
|
||||
&stepKeyPair{
|
||||
&ocommon.StepKeyPair{
|
||||
Debug: b.config.PackerDebug,
|
||||
DebugKeyPath: fmt.Sprintf("oci_%s.pem", b.config.PackerBuildName),
|
||||
PrivateKeyFile: b.config.Comm.SSHPrivateKey,
|
||||
|
@ -59,8 +60,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
&stepInstanceInfo{},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: commHost,
|
||||
SSHConfig: SSHConfig(
|
||||
Host: ocommon.CommHost,
|
||||
SSHConfig: ocommon.SSHConfig(
|
||||
b.config.Comm.SSHUsername,
|
||||
b.config.Comm.SSHPassword),
|
||||
},
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
nullbuilder "github.com/hashicorp/packer/builder/null"
|
||||
oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
|
||||
openstackbuilder "github.com/hashicorp/packer/builder/openstack"
|
||||
oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic"
|
||||
oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
|
||||
parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
|
||||
parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
|
||||
|
@ -99,6 +100,7 @@ var Builders = map[string]packer.Builder{
|
|||
"null": new(nullbuilder.Builder),
|
||||
"oneandone": new(oneandonebuilder.Builder),
|
||||
"openstack": new(openstackbuilder.Builder),
|
||||
"oracle-classic": new(oracleclassicbuilder.Builder),
|
||||
"oracle-oci": new(oracleocibuilder.Builder),
|
||||
"parallels-iso": new(parallelsisobuilder.Builder),
|
||||
"parallels-pvm": new(parallelspvmbuilder.Builder),
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
## 0.6.6 (January 11, 2018)
|
||||
|
||||
* compute: Create and delete machine images [GH-101]
|
||||
|
||||
## 0.6.5 (January 8, 2018)
|
||||
|
||||
* compute: Orchestration failures should explicitly tell the user why it failed [GH-100]
|
||||
|
||||
## 0.6.4 (Decemeber 20, 2017)
|
||||
|
||||
* compute: Added suspend functionality to orchestrated instances [GH-99]
|
||||
|
||||
## 0.6.3 (December 13, 2017)
|
||||
|
||||
* storage: Added remove header option to storage objects and containers [GH-96]
|
||||
|
||||
## 0.6.2 (November 28, 2017)
|
||||
|
||||
* client: Added a UserAgent to the Client [GH-98]
|
||||
|
||||
## 0.6.1 (Novemeber 26, 2017)
|
||||
|
||||
* compute: Added is_default_gateway to network attributes for instances [GH-97]
|
||||
|
||||
|
||||
## 0.6.0 (November 10, 2017)
|
||||
|
||||
* compute: Added is_default_gateway to network attributes for instances [GH-90]
|
||||
|
||||
* compute: Added the orchestration resource, specifically for instance creation [GH-91]
|
||||
|
||||
## 0.5.1 (October 5, 2017)
|
||||
|
||||
* java: Fixed subscription_type field
|
||||
|
||||
## 0.5.0 (October 5, 2017)
|
||||
|
||||
* java: Added more fields to java service instance [GH-89]
|
||||
|
||||
## 0.4.0 (September 14, 2017)
|
||||
|
||||
* database: Add utility resources [GH-87]
|
||||
|
||||
* compute: Increase storage volume snapshot create timeout [GH-88]
|
||||
|
||||
## 0.3.4 (August 16, 2017)
|
||||
|
||||
* storage_volumes: Actually capture errors during a storage volume create ([#86](https://github.com/hashicorp/go-oracle-terraform/issues/86))
|
||||
|
||||
## 0.3.3 (August 10, 2017)
|
||||
|
||||
* Add `ExposedHeaders` to storage containers ([#85](https://github.com/hashicorp/go-oracle-terraform/issues/85))
|
||||
|
||||
* Fixed `AllowedOrigins` in storage containers ([#85](https://github.com/hashicorp/go-oracle-terraform/issues/85))
|
||||
|
||||
## 0.3.2 (August 7, 2017)
|
||||
|
||||
* Add `id` for storage objects ([#84](https://github.com/hashicorp/go-oracle-terraform/issues/84))
|
||||
|
||||
## 0.3.1 (August 7, 2017)
|
||||
|
||||
* Update tests for Database parameter changes ([#83](https://github.com/hashicorp/go-oracle-terraform/issues/83))
|
||||
|
||||
## 0.3.0 (August 7, 2017)
|
||||
|
||||
* Add JaaS Service Instances ([#82](https://github.com/hashicorp/go-oracle-terraform/issues/82))
|
||||
|
||||
* Add storage objects ([#81](https://github.com/hashicorp/go-oracle-terraform/issues/81))
|
||||
|
||||
## 0.2.0 (July 27, 2017)
|
||||
|
||||
* service_instance: Switches yes/no strings to bool in input struct and then converts back to strings for ease of use on user end ([#80](https://github.com/hashicorp/go-oracle-terraform/issues/80))
|
||||
|
||||
## 0.1.9 (July 20, 2017)
|
||||
|
||||
* service_instance: Update delete retry count ([#79](https://github.com/hashicorp/go-oracle-terraform/issues/79))
|
||||
|
||||
* service_instance: Add additional fields ([#79](https://github.com/hashicorp/go-oracle-terraform/issues/79))
|
||||
|
||||
## 0.1.8 (July 19, 2017)
|
||||
|
||||
* storage_volumes: Add SSD support ([#78](https://github.com/hashicorp/go-oracle-terraform/issues/78))
|
||||
|
||||
## 0.1.7 (July 19, 2017)
|
||||
|
||||
* database: Adds the Oracle Database Cloud to the available sdks. ([#77](https://github.com/hashicorp/go-oracle-terraform/issues/77))
|
||||
|
||||
* database: Adds Service Instances to the database sdk ([#77](https://github.com/hashicorp/go-oracle-terraform/issues/77))
|
||||
|
||||
## 0.1.6 (July 18, 2017)
|
||||
|
||||
* opc: Add timeouts to instance and storage inputs ([#75](https://github.com/hashicorp/go-oracle-terraform/issues/75))
|
||||
|
||||
## 0.1.5 (July 5, 2017)
|
||||
|
||||
* storage: User must pass in Storage URL to CRUD resources ([#74](https://github.com/hashicorp/go-oracle-terraform/issues/74))
|
||||
|
||||
## 0.1.4 (June 30, 2017)
|
||||
|
||||
* opc: Fix infinite loop around auth token exceeding it's 25 minute duration. ([#73](https://github.com/hashicorp/go-oracle-terraform/issues/73))
|
||||
|
||||
## 0.1.3 (June 30, 2017)
|
||||
|
||||
* opc: Add additional logs instance logs ([#72](https://github.com/hashicorp/go-oracle-terraform/issues/72))
|
||||
|
||||
* opc: Increase instance creation and deletion timeout ([#72](https://github.com/hashicorp/go-oracle-terraform/issues/72))
|
||||
|
||||
## 0.1.2 (June 30, 2017)
|
||||
|
||||
|
||||
FEATURES:
|
||||
|
||||
* opc: Add image snapshots ([#67](https://github.com/hashicorp/go-oracle-terraform/issues/67))
|
||||
|
||||
* storage: Storage containers have been added ([#70](https://github.com/hashicorp/go-oracle-terraform/issues/70))
|
||||
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* opc: Refactored client to be generic for multiple Oracle api endpoints ([#68](https://github.com/hashicorp/go-oracle-terraform/issues/68))
|
||||
|
||||
* opc: Instance creation retries when an instance enters a deleted state ([#71](https://github.com/hashicorp/go-oracle-terraform/issues/71))
|
||||
|
||||
## 0.1.1 (May 31, 2017)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* opc: Add max_retries capabilities ([#66](https://github.com/hashicorp/go-oracle-terraform/issues/66))
|
||||
|
||||
## 0.1.0 (May 25, 2017)
|
||||
|
||||
BACKWARDS INCOMPATIBILITIES / NOTES:
|
||||
|
||||
* Initial Release of OPC SDK
|
|
@ -0,0 +1,41 @@
|
|||
TEST?=$$(go list ./... |grep -v 'vendor')
|
||||
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
|
||||
|
||||
test: fmtcheck errcheck
|
||||
go test -i $(TEST) || exit 1
|
||||
echo $(TEST) | \
|
||||
xargs -t -n4 go test $(TESTARGS) -timeout=60m -parallel=4
|
||||
|
||||
testacc: fmtcheck
|
||||
ORACLE_ACC=1 go test -v $(TEST) $(TESTARGS) -timeout 120m
|
||||
|
||||
testrace: fmtcheck
|
||||
ORACLE_ACC= go test -race $(TEST) $(TESTARGS)
|
||||
|
||||
cover:
|
||||
@go tool cover 2>/dev/null; if [ $$? -eq 3 ]; then \
|
||||
go get -u golang.org/x/tools/cmd/cover; \
|
||||
fi
|
||||
go test $(TEST) -coverprofile=coverage.out
|
||||
go tool cover -html=coverage.out
|
||||
rm coverage.out
|
||||
|
||||
vet:
|
||||
@echo "go vet ."
|
||||
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \
|
||||
echo ""; \
|
||||
echo "Vet found suspicious constructs. Please check the reported constructs"; \
|
||||
echo "and fix them if necessary before submitting the code for review."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
fmt:
|
||||
gofmt -w $(GOFMT_FILES)
|
||||
|
||||
fmtcheck:
|
||||
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"
|
||||
|
||||
errcheck:
|
||||
@sh -c "'$(CURDIR)/scripts/errcheck.sh'"
|
||||
|
||||
.PHONY: tools build test testacc testrace cover vet fmt fmtcheck errcheck
|
|
@ -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.
|
|
@ -0,0 +1,108 @@
|
|||
Oracle SDK for Terraform
|
||||
===========================================
|
||||
|
||||
**Note:** This SDK is _not_ meant to be a comprehensive SDK for Oracle Cloud. This is meant to be used solely with Terraform.
|
||||
|
||||
OPC Config
|
||||
----------
|
||||
|
||||
To create the Oracle clients, a populated configuration struct is required.
|
||||
The config struct holds the following fields:
|
||||
|
||||
* `Username` - (`*string`) The Username used to authenticate to Oracle Public Cloud.
|
||||
* `Password` - (`*string`) The Password used to authenticate to Oracle Public Cloud.
|
||||
* `IdentityDomain` - (`*string`) The identity domain for Oracle Public Cloud.
|
||||
* `APIEndpoint` - (`*url.URL`) The API Endpoint provided by Oracle Public Cloud.
|
||||
* `LogLevel` - (`LogLevelType`) Defaults to `opc.LogOff`, can be either `opc.LogOff` or `opc.LogDebug`.
|
||||
* `Logger` - (`Logger`) Must satisfy the generic `Logger` interface. Defaults to `ioutil.Discard` for the `LogOff` loglevel, and `os.Stderr` for the `LogDebug` loglevel.
|
||||
* `HTTPClient` - (`*http.Client`) Defaults to generic HTTP Client if unspecified.
|
||||
|
||||
Oracle Compute Client
|
||||
----------------------
|
||||
The Oracle Compute Client requires an OPC Config object to be populated in order to create the client.
|
||||
|
||||
Full example to create an OPC Compute instance:
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"github.com/hashicorp/go-oracle-terraform/opc"
|
||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiEndpoint, err := url.Parse("myAPIEndpoint")
|
||||
if err != nil {
|
||||
fmt.Errorf("Error parsing API Endpoint: %s", err)
|
||||
}
|
||||
|
||||
config := &opc.Config{
|
||||
Username: opc.String("myusername"),
|
||||
Password: opc.String("mypassword"),
|
||||
IdentityDomain: opc.String("myidentitydomain"),
|
||||
APIEndpoint: apiEndpoint,
|
||||
LogLevel: opc.LogDebug,
|
||||
// Logger: # Leave blank to use the default logger, or provide your own
|
||||
// HTTPClient: # Leave blank to use default HTTP Client, or provider your own
|
||||
}
|
||||
// Create the Compute Client
|
||||
client, err := compute.NewComputeClient(config)
|
||||
if err != nil {
|
||||
fmt.Errorf("Error creating OPC Compute Client: %s", err)
|
||||
}
|
||||
// Create instances client
|
||||
instanceClient := client.Instances()
|
||||
|
||||
// Instances Input
|
||||
input := &compute.CreateInstanceInput{
|
||||
Name: "test-instance",
|
||||
Label: "test",
|
||||
Shape: "oc3",
|
||||
ImageList: "/oracle/public/oel_6.7_apaas_16.4.5_1610211300",
|
||||
Storage: nil,
|
||||
BootOrder: nil,
|
||||
SSHKeys: []string{},
|
||||
Attributes: map[string]interface{}{},
|
||||
}
|
||||
|
||||
// Create the instance
|
||||
instance, err := instanceClient.CreateInstance(input)
|
||||
if err != nil {
|
||||
fmt.Errorf("Error creating instance: %s", err)
|
||||
}
|
||||
fmt.Printf("Instance Created: %#v", instance)
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to inline documentation for each resource that the compute client provides.
|
||||
|
||||
Running the SDK Integration Tests
|
||||
-----------------------------
|
||||
|
||||
To authenticate with the Oracle Compute Cloud the following credentails must be set in the following environment variables:
|
||||
|
||||
- `OPC_ENDPOINT` - Endpoint provided by Oracle Public Cloud (e.g. https://api-z13.compute.em2.oraclecloud.com/\)
|
||||
- `OPC_USERNAME` - Username for Oracle Public Cloud
|
||||
- `OPC_PASSWORD` - Password for Oracle Public Cloud
|
||||
- `OPC_IDENTITY_DOMAIN` - Identity domain for Oracle Public Cloud
|
||||
|
||||
|
||||
The Integration tests can be ran with the following command:
|
||||
```sh
|
||||
$ make testacc
|
||||
```
|
||||
|
||||
Isolating a single SDK package can be done via the `TEST` environment variable
|
||||
```sh
|
||||
$ make testacc TEST=./compute
|
||||
```
|
||||
|
||||
Isolating a single test within a package can be done via the `TESTARGS` environment variable
|
||||
```sh
|
||||
$ make testacc TEST=./compute TESTARGS='-run=TestAccIPAssociationLifeCycle'
|
||||
```
|
||||
|
||||
Tests are ran with logs being sent to `ioutil.Discard` by default.
|
||||
Display debug logs inside of tests by setting the `ORACLE_LOG` environment variable to any value.
|
|
@ -0,0 +1,245 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/opc"
|
||||
)
|
||||
|
||||
const DEFAULT_MAX_RETRIES = 1
|
||||
const USER_AGENT_HEADER = "User-Agent"
|
||||
|
||||
var (
|
||||
// defaultUserAgent builds a string containing the Go version, system archityecture and OS,
|
||||
// and the go-autorest version.
|
||||
defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-oracle-terraform/%s",
|
||||
runtime.Version(),
|
||||
runtime.GOARCH,
|
||||
runtime.GOOS,
|
||||
Version(),
|
||||
)
|
||||
)
|
||||
|
||||
// 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
|
||||
MaxRetries *int
|
||||
UserAgent *string
|
||||
logger opc.Logger
|
||||
loglevel opc.LogLevelType
|
||||
}
|
||||
|
||||
func NewClient(c *opc.Config) (*Client, error) {
|
||||
// First create a client
|
||||
client := &Client{
|
||||
IdentityDomain: c.IdentityDomain,
|
||||
UserName: c.Username,
|
||||
Password: c.Password,
|
||||
APIEndpoint: c.APIEndpoint,
|
||||
UserAgent: &defaultUserAgent,
|
||||
httpClient: c.HTTPClient,
|
||||
MaxRetries: c.MaxRetries,
|
||||
loglevel: c.LogLevel,
|
||||
}
|
||||
if c.UserAgent != nil {
|
||||
client.UserAgent = c.UserAgent
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// Default max retries if unset
|
||||
if c.MaxRetries == nil {
|
||||
client.MaxRetries = opc.Int(DEFAULT_MAX_RETRIES)
|
||||
}
|
||||
|
||||
// Protect against any nil http client
|
||||
if c.HTTPClient == nil {
|
||||
return nil, fmt.Errorf("No HTTP client specified in config")
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Marshalls the request body and returns the resulting byte slice
|
||||
// This is split out of the BuildRequestBody method so as to allow
|
||||
// the developer to print a debug string of the request body if they
|
||||
// should so choose.
|
||||
func (c *Client) MarshallRequestBody(body interface{}) ([]byte, error) {
|
||||
// Verify interface isnt' nil
|
||||
if body == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return json.Marshal(body)
|
||||
}
|
||||
|
||||
// Builds an HTTP Request that accepts a pre-marshaled body parameter as a raw byte array
|
||||
// Returns the raw HTTP Request and any error occured
|
||||
func (c *Client) BuildRequestBody(method, path string, body []byte) (*http.Request, error) {
|
||||
// Parse URL Path
|
||||
urlPath, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var requestBody io.ReadSeeker
|
||||
if len(body) != 0 {
|
||||
requestBody = bytes.NewReader(body)
|
||||
}
|
||||
|
||||
// Create Request
|
||||
req, err := http.NewRequest(method, c.formatURL(urlPath), requestBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Adding UserAgent Header
|
||||
req.Header.Add(USER_AGENT_HEADER, *c.UserAgent)
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// Build a new HTTP request that doesn't marshall the request body
|
||||
func (c *Client) BuildNonJSONRequest(method, path string, body io.ReadSeeker) (*http.Request, error) {
|
||||
// Parse URL Path
|
||||
urlPath, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create request
|
||||
req, err := http.NewRequest(method, c.formatURL(urlPath), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Adding UserAgentHeader
|
||||
req.Header.Add(USER_AGENT_HEADER, *c.UserAgent)
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// This method executes the http.Request from the BuildRequest method.
|
||||
// It is split up to add additional authentication that is Oracle API dependent.
|
||||
func (c *Client) ExecuteRequest(req *http.Request) (*http.Response, error) {
|
||||
// Execute request with supplied client
|
||||
resp, err := c.retryRequest(req)
|
||||
if err != nil {
|
||||
return resp, 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()
|
||||
}
|
||||
|
||||
// Should return the response object regardless of error,
|
||||
// some resources need to verify and check status code on errors to
|
||||
// determine if an error actually occurs or not.
|
||||
return resp, oracleErr
|
||||
}
|
||||
|
||||
// Allow retrying the request until it either returns no error,
|
||||
// or we exceed the number of max retries
|
||||
func (c *Client) retryRequest(req *http.Request) (*http.Response, error) {
|
||||
// Double check maxRetries is not nil
|
||||
var retries int
|
||||
if c.MaxRetries == nil {
|
||||
retries = DEFAULT_MAX_RETRIES
|
||||
} else {
|
||||
retries = *c.MaxRetries
|
||||
}
|
||||
|
||||
var statusCode int
|
||||
var errMessage string
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(resp.Body)
|
||||
errMessage = buf.String()
|
||||
statusCode = resp.StatusCode
|
||||
c.DebugLogString(fmt.Sprintf("Encountered HTTP (%d) Error: %s", statusCode, errMessage))
|
||||
c.DebugLogString(fmt.Sprintf("%d/%d retries left", i+1, retries))
|
||||
}
|
||||
|
||||
oracleErr := &opc.OracleError{
|
||||
StatusCode: statusCode,
|
||||
Message: errMessage,
|
||||
}
|
||||
|
||||
// We ran out of retries to make, return the error and response
|
||||
return nil, oracleErr
|
||||
}
|
||||
|
||||
func (c *Client) formatURL(path *url.URL) string {
|
||||
return c.APIEndpoint.ResolveReference(path).String()
|
||||
}
|
||||
|
||||
// Retry function
|
||||
func (c *Client) WaitFor(description string, timeout time.Duration, test func() (bool, error)) error {
|
||||
tick := time.Tick(1 * time.Second)
|
||||
|
||||
timeoutSeconds := int(timeout.Seconds())
|
||||
|
||||
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
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package client
|
||||
|
||||
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()))
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
major = 0
|
||||
minor = 6
|
||||
patch = 2
|
||||
tag = ""
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
var version string
|
||||
|
||||
// Version returns the semantic version (see http://semver.org).
|
||||
func Version() string {
|
||||
once.Do(func() {
|
||||
semver := fmt.Sprintf("%d.%d.%d", major, minor, patch)
|
||||
verBuilder := bytes.NewBufferString(semver)
|
||||
if tag != "" && tag != "-" {
|
||||
updated := strings.TrimPrefix(tag, "-")
|
||||
_, err := verBuilder.WriteString("-" + updated)
|
||||
if err == nil {
|
||||
verBuilder = bytes.NewBufferString(semver)
|
||||
}
|
||||
}
|
||||
version = verBuilder.String()
|
||||
})
|
||||
return version
|
||||
}
|
|
@ -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 *ComputeClient) ACLs() *ACLsClient {
|
||||
return &ACLsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
34
vendor/github.com/hashicorp/go-oracle-terraform/compute/authentication.go
generated
vendored
Normal file
34
vendor/github.com/hashicorp/go-oracle-terraform/compute/authentication.go
generated
vendored
Normal 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 *ComputeClient) getAuthenticationCookie() error {
|
||||
req := AuthenticationReq{
|
||||
User: c.getUserName(),
|
||||
Password: *c.client.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.client.DebugLogString("Successfully authenticated to OPC")
|
||||
c.authCookie = rsp.Cookies()[0]
|
||||
c.cookieIssued = time.Now()
|
||||
return nil
|
||||
}
|
167
vendor/github.com/hashicorp/go-oracle-terraform/compute/compute_client.go
generated
vendored
Normal file
167
vendor/github.com/hashicorp/go-oracle-terraform/compute/compute_client.go
generated
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
"github.com/hashicorp/go-oracle-terraform/opc"
|
||||
)
|
||||
|
||||
const CMP_ACME = "/Compute-%s"
|
||||
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 ComputeClient struct {
|
||||
client *client.Client
|
||||
authCookie *http.Cookie
|
||||
cookieIssued time.Time
|
||||
}
|
||||
|
||||
func NewComputeClient(c *opc.Config) (*ComputeClient, error) {
|
||||
computeClient := &ComputeClient{}
|
||||
client, err := client.NewClient(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
computeClient.client = client
|
||||
|
||||
if err := computeClient.getAuthenticationCookie(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return computeClient, nil
|
||||
}
|
||||
|
||||
func (c *ComputeClient) executeRequest(method, path string, body interface{}) (*http.Response, error) {
|
||||
reqBody, err := c.client.MarshallRequestBody(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := c.client.BuildRequestBody(method, path, reqBody)
|
||||
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 credentials in STDERR
|
||||
if path != "/authenticate/" {
|
||||
debugReqString = fmt.Sprintf("%s:\n %+v", debugReqString, string(reqBody))
|
||||
}
|
||||
}
|
||||
// Log the request before the authentication cookie, so as not to leak credentials
|
||||
c.client.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 {
|
||||
c.authCookie = nil
|
||||
if err := c.getAuthenticationCookie(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
req.AddCookie(c.authCookie)
|
||||
}
|
||||
|
||||
resp, err := c.client.ExecuteRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *ComputeClient) getACME() string {
|
||||
return fmt.Sprintf(CMP_ACME, *c.client.IdentityDomain)
|
||||
}
|
||||
|
||||
func (c *ComputeClient) getUserName() string {
|
||||
return fmt.Sprintf(CMP_USERNAME, *c.client.IdentityDomain, *c.client.UserName)
|
||||
}
|
||||
|
||||
func (c *ComputeClient) getQualifiedACMEName(name string) string {
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.HasPrefix(name, "/Compute-") && len(strings.Split(name, "/")) == 1 {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf(CMP_QUALIFIED_NAME, c.getACME(), name)
|
||||
}
|
||||
|
||||
// From compute_client
|
||||
// GetObjectName returns the fully-qualified name of an OPC object, e.g. /identity-domain/user@email/{name}
|
||||
func (c *ComputeClient) 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 *ComputeClient) 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 *ComputeClient) 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 *ComputeClient) unqualify(names ...*string) {
|
||||
for _, name := range names {
|
||||
*name = c.getUnqualifiedName(*name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ComputeClient) unqualifyUrl(url *string) {
|
||||
var validID = regexp.MustCompile(`(\/(Compute[^\/\s]+))(\/[^\/\s]+)(\/[^\/\s]+)`)
|
||||
name := validID.FindString(*url)
|
||||
*url = c.getUnqualifiedName(name)
|
||||
}
|
||||
|
||||
func (c *ComputeClient) getQualifiedList(list []string) []string {
|
||||
for i, name := range list {
|
||||
list[i] = c.getQualifiedName(name)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *ComputeClient) getUnqualifiedList(list []string) []string {
|
||||
for i, name := range list {
|
||||
list[i] = c.getUnqualifiedName(name)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *ComputeClient) 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 *ComputeClient) unqualifyListName(qualifiedName string) string {
|
||||
nameParts := strings.Split(qualifiedName, ":")
|
||||
listType := nameParts[0]
|
||||
listName := nameParts[1]
|
||||
return fmt.Sprintf("%s:%s", listType, c.getUnqualifiedName(listName))
|
||||
}
|
113
vendor/github.com/hashicorp/go-oracle-terraform/compute/compute_resource_client.go
generated
vendored
Normal file
113
vendor/github.com/hashicorp/go-oracle-terraform/compute/compute_resource_client.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
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 {
|
||||
*ComputeClient
|
||||
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) deleteOrchestration(name string) error {
|
||||
var objectPath string
|
||||
if name != "" {
|
||||
objectPath = c.getObjectPath(c.ResourceRootPath, name)
|
||||
} else {
|
||||
objectPath = c.ResourceRootPath
|
||||
}
|
||||
// Set terminate to true as we always want to delete an orchestration
|
||||
objectPath = fmt.Sprintf("%s?terminate=True", objectPath)
|
||||
|
||||
_, 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.client.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
|
||||
}
|
154
vendor/github.com/hashicorp/go-oracle-terraform/compute/image_list.go
generated
vendored
Normal file
154
vendor/github.com/hashicorp/go-oracle-terraform/compute/image_list.go
generated
vendored
Normal 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 *ComputeClient) ImageList() *ImageListClient {
|
||||
return &ImageListClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
122
vendor/github.com/hashicorp/go-oracle-terraform/compute/image_list_entries.go
generated
vendored
Normal file
122
vendor/github.com/hashicorp/go-oracle-terraform/compute/image_list_entries.go
generated
vendored
Normal 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 *ComputeClient) ImageListEntries() *ImageListEntriesClient {
|
||||
return &ImageListEntriesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
788
vendor/github.com/hashicorp/go-oracle-terraform/compute/instances.go
generated
vendored
Normal file
788
vendor/github.com/hashicorp/go-oracle-terraform/compute/instances.go
generated
vendored
Normal file
|
@ -0,0 +1,788 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
)
|
||||
|
||||
const WaitForInstanceReadyTimeout = time.Duration(3600 * time.Second)
|
||||
const WaitForInstanceDeleteTimeout = time.Duration(3600 * time.Second)
|
||||
|
||||
// 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 *ComputeClient) Instances() *InstancesClient {
|
||||
return &InstancesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "instance",
|
||||
ContainerPath: "/launchplan/",
|
||||
ResourceRootPath: "/instance",
|
||||
}}
|
||||
}
|
||||
|
||||
type InstanceState string
|
||||
|
||||
const (
|
||||
InstanceRunning InstanceState = "running"
|
||||
InstanceInitializing InstanceState = "initializing"
|
||||
InstancePreparing InstanceState = "preparing"
|
||||
InstanceStarting InstanceState = "starting"
|
||||
InstanceStopping InstanceState = "stopping"
|
||||
InstanceShutdown InstanceState = "shutdown"
|
||||
InstanceQueued InstanceState = "queued"
|
||||
InstanceError InstanceState = "error"
|
||||
)
|
||||
|
||||
type InstanceDesiredState string
|
||||
|
||||
const (
|
||||
InstanceDesiredRunning InstanceDesiredState = "running"
|
||||
InstanceDesiredShutdown InstanceDesiredState = "shutdown"
|
||||
)
|
||||
|
||||
// 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"`
|
||||
|
||||
// The desired state of an instance
|
||||
DesiredState InstanceDesiredState `json:"desired_state"`
|
||||
|
||||
// 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,omitempty"`
|
||||
// The desired state of the opc instance. Can only be `running` or `shutdown`
|
||||
// Omits if empty.
|
||||
// Optional
|
||||
DesiredState InstanceDesiredState `json:"desired_state,omitempty"`
|
||||
// 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,omitempty"`
|
||||
// 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"`
|
||||
// Time to wait for an instance to be ready
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
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.
|
||||
// Set interface as default gateway for all traffic
|
||||
// Optional
|
||||
IsDefaultGateway bool `json:"is_default_gateway,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"`
|
||||
// Time to wait for instance boot
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
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},
|
||||
Timeout: input.Timeout,
|
||||
}
|
||||
|
||||
var (
|
||||
instanceInfo *InstanceInfo
|
||||
instanceError error
|
||||
)
|
||||
for i := 0; i < *c.ComputeClient.client.MaxRetries; i++ {
|
||||
c.client.DebugLogString(fmt.Sprintf("(Iteration: %d of %d) Creating instance with name %s\n Plan: %+v", i, *c.ComputeClient.client.MaxRetries, input.Name, plan))
|
||||
|
||||
instanceInfo, instanceError = c.startInstance(input.Name, plan)
|
||||
if instanceError == nil {
|
||||
c.client.DebugLogString(fmt.Sprintf("(Iteration: %d of %d) Finished creating instance with name %s\n Info: %+v", i, *c.ComputeClient.client.MaxRetries, input.Name, instanceInfo))
|
||||
return instanceInfo, nil
|
||||
}
|
||||
}
|
||||
return nil, instanceError
|
||||
}
|
||||
|
||||
func (c *InstancesClient) startInstance(name string, plan LaunchPlanInput) (*InstanceInfo, error) {
|
||||
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: name,
|
||||
ID: responseBody.Instances[0].ID,
|
||||
}
|
||||
|
||||
//timeout := WaitForInstanceReadyTimeout
|
||||
if plan.Timeout == 0 {
|
||||
plan.Timeout = WaitForInstanceReadyTimeout
|
||||
}
|
||||
|
||||
// Wait for instance to be ready and return the result
|
||||
// Don't have to unqualify any objects, as the GetInstance method will handle that
|
||||
instanceInfo, instanceError := c.WaitForInstanceRunning(getInput, plan.Timeout)
|
||||
// If the instance enters an error state we need to delete the instance and retry
|
||||
if instanceError != nil {
|
||||
deleteInput := &DeleteInstanceInput{
|
||||
Name: name,
|
||||
ID: responseBody.Instances[0].ID,
|
||||
}
|
||||
err := c.DeleteInstance(deleteInput)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error deleting instance %s: %s", name, err)
|
||||
}
|
||||
return nil, instanceError
|
||||
}
|
||||
return instanceInfo, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
var networkingErr error
|
||||
responseBody.Networking, networkingErr = c.unqualifyNetworking(responseBody.Networking)
|
||||
if networkingErr != nil {
|
||||
return nil, networkingErr
|
||||
}
|
||||
responseBody.Storage = c.unqualifyStorage(responseBody.Storage)
|
||||
|
||||
return &responseBody, nil
|
||||
}
|
||||
|
||||
type InstancesInfo struct {
|
||||
Instances []InstanceInfo `json:"result"`
|
||||
}
|
||||
|
||||
type GetInstanceIdInput struct {
|
||||
// Name of the instance you want to get
|
||||
Name string
|
||||
}
|
||||
|
||||
// GetInstanceFromName loops through all the instances and finds the instance for the given name
|
||||
// This is needed for orchestration since it doesn't return the id for the instance it creates.
|
||||
func (c *InstancesClient) GetInstanceFromName(input *GetInstanceIdInput) (*InstanceInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
|
||||
var instancesInfo InstancesInfo
|
||||
if err := c.getResource(fmt.Sprintf("%s/", c.getUserName()), &instancesInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, i := range instancesInfo.Instances {
|
||||
if strings.Contains(i.Name, input.Name) {
|
||||
if i.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(i.Name), "/")
|
||||
i.Name = nID[0]
|
||||
i.ID = nID[1]
|
||||
|
||||
c.unqualify(&i.VCableID)
|
||||
|
||||
// Unqualify SSH Key names
|
||||
sshKeyNames := []string{}
|
||||
for _, sshKeyRef := range i.SSHKeys {
|
||||
sshKeyNames = append(sshKeyNames, c.getUnqualifiedName(sshKeyRef))
|
||||
}
|
||||
i.SSHKeys = sshKeyNames
|
||||
|
||||
var networkingErr error
|
||||
i.Networking, networkingErr = c.unqualifyNetworking(i.Networking)
|
||||
if networkingErr != nil {
|
||||
return nil, networkingErr
|
||||
}
|
||||
i.Storage = c.unqualifyStorage(i.Storage)
|
||||
|
||||
return &i, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unable to find instance: %q", input.Name)
|
||||
}
|
||||
|
||||
type UpdateInstanceInput struct {
|
||||
// Name of this instance, generated by the server.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
// The desired state of the opc instance. Can only be `running` or `shutdown`
|
||||
// Omits if empty.
|
||||
// Optional
|
||||
DesiredState InstanceDesiredState `json:"desired_state,omitempty"`
|
||||
// The ID of the instance
|
||||
// Required
|
||||
ID string `json:"-"`
|
||||
// A list of tags to be supplied to the instance
|
||||
// Optional
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
// Time to wait for instance to be ready, or shutdown depending on desired state
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
func (g *UpdateInstanceInput) String() string {
|
||||
return fmt.Sprintf(CMP_QUALIFIED_NAME, g.Name, g.ID)
|
||||
}
|
||||
|
||||
func (c *InstancesClient) UpdateInstance(input *UpdateInstanceInput) (*InstanceInfo, error) {
|
||||
if input.Name == "" || input.ID == "" {
|
||||
return nil, errors.New("Both instance name and ID need to be specified")
|
||||
}
|
||||
|
||||
input.Name = fmt.Sprintf(CMP_QUALIFIED_NAME, c.getUserName(), input.Name)
|
||||
|
||||
var responseBody InstanceInfo
|
||||
if err := c.updateResource(input.String(), input, &responseBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
getInput := &GetInstanceInput{
|
||||
Name: input.Name,
|
||||
ID: input.ID,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForInstanceReadyTimeout
|
||||
}
|
||||
|
||||
// Wait for the correct instance action depending on the current desired state.
|
||||
// If the instance is already running, and the desired state is to be "running", the
|
||||
// wait loop will only execute a single time to verify the instance state. Otherwise
|
||||
// we wait until the correct action has finalized, either a shutdown or restart, catching
|
||||
// any intermittent errors during the process.
|
||||
if responseBody.DesiredState == InstanceDesiredRunning {
|
||||
return c.WaitForInstanceRunning(getInput, input.Timeout)
|
||||
} else {
|
||||
return c.WaitForInstanceShutdown(getInput, input.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteInstanceInput struct {
|
||||
// The Unqualified Name of this Instance
|
||||
Name string
|
||||
// The Unqualified ID of this Instance
|
||||
ID string
|
||||
// Time to wait for instance to be deleted
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForInstanceDeleteTimeout
|
||||
}
|
||||
|
||||
// Wait for instance to be deleted
|
||||
return c.WaitForInstanceDeleted(input, input.Timeout)
|
||||
}
|
||||
|
||||
// WaitForInstanceRunning waits for an instance to be completely initialized and available.
|
||||
func (c *InstancesClient) WaitForInstanceRunning(input *GetInstanceInput, timeout time.Duration) (*InstanceInfo, error) {
|
||||
var info *InstanceInfo
|
||||
var getErr error
|
||||
err := c.client.WaitFor("instance to be ready", timeout, func() (bool, error) {
|
||||
info, getErr = c.GetInstance(input)
|
||||
if getErr != nil {
|
||||
return false, getErr
|
||||
}
|
||||
c.client.DebugLogString(fmt.Sprintf("Instance name is %v, Instance info is %+v", info.Name, info))
|
||||
switch s := info.State; s {
|
||||
case InstanceError:
|
||||
return false, fmt.Errorf("Error initializing instance: %s", info.ErrorReason)
|
||||
case InstanceRunning: // Target State
|
||||
c.client.DebugLogString("Instance Running")
|
||||
return true, nil
|
||||
case InstanceQueued:
|
||||
c.client.DebugLogString("Instance Queuing")
|
||||
return false, nil
|
||||
case InstanceInitializing:
|
||||
c.client.DebugLogString("Instance Initializing")
|
||||
return false, nil
|
||||
case InstancePreparing:
|
||||
c.client.DebugLogString("Instance Preparing")
|
||||
return false, nil
|
||||
case InstanceStarting:
|
||||
c.client.DebugLogString("Instance Starting")
|
||||
return false, nil
|
||||
default:
|
||||
c.client.DebugLogString(fmt.Sprintf("Unknown instance state: %s, waiting", s))
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
return info, err
|
||||
}
|
||||
|
||||
// WaitForInstanceShutdown waits for an instance to be shutdown
|
||||
func (c *InstancesClient) WaitForInstanceShutdown(input *GetInstanceInput, timeout time.Duration) (*InstanceInfo, error) {
|
||||
var info *InstanceInfo
|
||||
var getErr error
|
||||
err := c.client.WaitFor("instance to be shutdown", timeout, 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.client.DebugLogString("Instance Running")
|
||||
return false, nil
|
||||
case InstanceQueued:
|
||||
c.client.DebugLogString("Instance Queuing")
|
||||
return false, nil
|
||||
case InstanceInitializing:
|
||||
c.client.DebugLogString("Instance Initializing")
|
||||
return false, nil
|
||||
case InstancePreparing:
|
||||
c.client.DebugLogString("Instance Preparing")
|
||||
return false, nil
|
||||
case InstanceStarting:
|
||||
c.client.DebugLogString("Instance Starting")
|
||||
return false, nil
|
||||
case InstanceShutdown: // Target State
|
||||
c.client.DebugLogString("Instance Shutdown")
|
||||
return true, nil
|
||||
default:
|
||||
c.client.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, timeout time.Duration) error {
|
||||
return c.client.WaitFor("instance to be deleted", timeout, func() (bool, error) {
|
||||
var info InstanceInfo
|
||||
if err := c.getResource(input.String(), &info); err != nil {
|
||||
if client.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.client.DebugLogString("Instance stopping")
|
||||
return false, nil
|
||||
default:
|
||||
c.client.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, error) {
|
||||
// Unqualify ip network
|
||||
var err error
|
||||
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, err = c.unqualifyNat(v.Nat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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, nil
|
||||
}
|
||||
|
||||
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, error) {
|
||||
unQualifiedNats := []string{}
|
||||
for _, v := range nat {
|
||||
if strings.HasPrefix(v, "ippool:/oracle") {
|
||||
unQualifiedNats = append(unQualifiedNats, v)
|
||||
continue
|
||||
}
|
||||
n := strings.Split(v, ":")
|
||||
if len(n) < 1 {
|
||||
return nil, fmt.Errorf("Error unqualifying NAT: %s", v)
|
||||
}
|
||||
u := n[1]
|
||||
unQualifiedNats = append(unQualifiedNats, c.getUnqualifiedName(u))
|
||||
}
|
||||
return unQualifiedNats, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
152
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go
generated
vendored
Normal file
152
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_associations.go
generated
vendored
Normal 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 *ComputeClient) IPAddressAssociations() *IPAddressAssociationsClient {
|
||||
return &IPAddressAssociationsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
135
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_prefix_set.go
generated
vendored
Normal file
135
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_prefix_set.go
generated
vendored
Normal 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 *ComputeClient) IPAddressPrefixSets() *IPAddressPrefixSetsClient {
|
||||
return &IPAddressPrefixSetsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
190
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_reservations.go
generated
vendored
Normal file
190
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_address_reservations.go
generated
vendored
Normal 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 *ComputeClient) IPAddressReservations() *IPAddressReservationsClient {
|
||||
return &IPAddressReservationsClient{
|
||||
ResourceClient: &ResourceClient{
|
||||
ComputeClient: 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)
|
||||
}
|
118
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_associations.go
generated
vendored
Normal file
118
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_associations.go
generated
vendored
Normal 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 *ComputeClient) IPAssociations() *IPAssociationsClient {
|
||||
return &IPAssociationsClient{
|
||||
ResourceClient: &ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
99
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_network_exchange.go
generated
vendored
Normal file
99
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_network_exchange.go
generated
vendored
Normal 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 *ComputeClient) IPNetworkExchanges() *IPNetworkExchangesClient {
|
||||
return &IPNetworkExchangesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
186
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_networks.go
generated
vendored
Normal file
186
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_networks.go
generated
vendored
Normal 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 *ComputeClient) IPNetworks() *IPNetworksClient {
|
||||
return &IPNetworksClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
147
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_reservations.go
generated
vendored
Normal file
147
vendor/github.com/hashicorp/go-oracle-terraform/compute/ip_reservations.go
generated
vendored
Normal 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 *ComputeClient) IPReservations() *IPReservationsClient {
|
||||
return &IPReservationsClient{
|
||||
ResourceClient: &ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
143
vendor/github.com/hashicorp/go-oracle-terraform/compute/machine_images.go
generated
vendored
Normal file
143
vendor/github.com/hashicorp/go-oracle-terraform/compute/machine_images.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
package compute
|
||||
|
||||
// MachineImagesClient is a client for the MachineImage functions of the Compute API.
|
||||
type MachineImagesClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// MachineImages obtains an MachineImagesClient which can be used to access to the
|
||||
// MachineImage functions of the Compute API
|
||||
func (c *ComputeClient) MachineImages() *MachineImagesClient {
|
||||
return &MachineImagesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "MachineImage",
|
||||
ContainerPath: "/machineimage/",
|
||||
ResourceRootPath: "/machineimage",
|
||||
}}
|
||||
}
|
||||
|
||||
// MahineImage describes an existing Machine Image.
|
||||
type MachineImage struct {
|
||||
// account of the associated Object Storage Classic instance
|
||||
Account string `json:"account"`
|
||||
|
||||
// Dictionary of attributes to be made available to the instance
|
||||
Attributes map[string]interface{} `json:"attributes"`
|
||||
|
||||
// Last time when this image was audited
|
||||
Audited string `json:"audited"`
|
||||
|
||||
// Describing the image
|
||||
Description string `json:"description"`
|
||||
|
||||
// Description of the state of the machine image if there is an error
|
||||
ErrorReason string `json:"error_reason"`
|
||||
|
||||
// dictionary of hypervisor-specific attributes
|
||||
Hypervisor map[string]interface{} `json:"hypervisor"`
|
||||
|
||||
// The format of the image
|
||||
ImageFormat string `json:"image_format"`
|
||||
|
||||
// name of the machine image file uploaded to Object Storage Classic
|
||||
File string `json:"file"`
|
||||
|
||||
// name of the machine image
|
||||
Name string `json:"name"`
|
||||
|
||||
// Indicates that the image file is available in Object Storage Classic
|
||||
NoUpload bool `json:"no_upload"`
|
||||
|
||||
// The OS platform of the image
|
||||
Platform string `json:"platform"`
|
||||
|
||||
// Size values of the image file
|
||||
Sizes map[string]interface{} `json:"sizes"`
|
||||
|
||||
// The state of the uploaded machine image
|
||||
State string `json:"state"`
|
||||
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
// CreateMachineImageInput defines an Image List to be created.
|
||||
type CreateMachineImageInput struct {
|
||||
// account of the associated Object Storage Classic instance
|
||||
Account string `json:"account"`
|
||||
|
||||
// Dictionary of attributes to be made available to the instance
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
|
||||
// Describing the image
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// name of the machine image file uploaded to Object Storage Classic
|
||||
File string `json:"file,omitempty"`
|
||||
|
||||
// name of the machine image
|
||||
Name string `json:"name"`
|
||||
|
||||
// Indicates that the image file is available in Object Storage Classic
|
||||
NoUpload bool `json:"no_upload"`
|
||||
|
||||
// Size values of the image file
|
||||
Sizes map[string]interface{} `json:"sizes"`
|
||||
}
|
||||
|
||||
// CreateMachineImage creates a new Machine Image with the given parameters.
|
||||
func (c *MachineImagesClient) CreateMachineImage(createInput *CreateMachineImageInput) (*MachineImage, error) {
|
||||
var machineImage MachineImage
|
||||
|
||||
// If `sizes` is not set then is mst be defaulted to {"total": 0}
|
||||
if createInput.Sizes == nil {
|
||||
createInput.Sizes = map[string]interface{}{"total": 0}
|
||||
}
|
||||
|
||||
// `no_upload` must always be true
|
||||
createInput.NoUpload = true
|
||||
|
||||
createInput.Name = c.getQualifiedName(createInput.Name)
|
||||
if err := c.createResource(createInput, &machineImage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&machineImage)
|
||||
}
|
||||
|
||||
// DeleteMachineImageInput describes the MachineImage to delete
|
||||
type DeleteMachineImageInput struct {
|
||||
// The name of the MachineImage
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// DeleteMachineImage deletes the MachineImage with the given name.
|
||||
func (c *MachineImagesClient) DeleteMachineImage(deleteInput *DeleteMachineImageInput) error {
|
||||
return c.deleteResource(deleteInput.Name)
|
||||
}
|
||||
|
||||
// GetMachineList describes the MachineImage to get
|
||||
type GetMachineImageInput struct {
|
||||
// account of the associated Object Storage Classic instance
|
||||
Account string `json:"account"`
|
||||
// The name of the Machine Image
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// GetMachineImage retrieves the MachineImage with the given name.
|
||||
func (c *MachineImagesClient) GetMachineImage(getInput *GetMachineImageInput) (*MachineImage, error) {
|
||||
getInput.Name = c.getQualifiedName(getInput.Name)
|
||||
|
||||
var machineImage MachineImage
|
||||
if err := c.getResource(getInput.Name, &machineImage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&machineImage)
|
||||
}
|
||||
|
||||
func (c *MachineImagesClient) success(result *MachineImage) (*MachineImage, error) {
|
||||
c.unqualify(&result.Name)
|
||||
return result, nil
|
||||
}
|
451
vendor/github.com/hashicorp/go-oracle-terraform/compute/orchestration.go
generated
vendored
Normal file
451
vendor/github.com/hashicorp/go-oracle-terraform/compute/orchestration.go
generated
vendored
Normal file
|
@ -0,0 +1,451 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
)
|
||||
|
||||
const WaitForOrchestrationActiveTimeout = time.Duration(3600 * time.Second)
|
||||
const WaitForOrchestrationDeleteTimeout = time.Duration(3600 * time.Second)
|
||||
|
||||
// OrchestrationsClient is a client for the Orchestration functions of the Compute API.
|
||||
type OrchestrationsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// Orchestrations obtains an OrchestrationsClient which can be used to access to the
|
||||
// Orchestration functions of the Compute API
|
||||
func (c *ComputeClient) Orchestrations() *OrchestrationsClient {
|
||||
return &OrchestrationsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "Orchestration",
|
||||
ContainerPath: "/platform/v1/orchestration/",
|
||||
ResourceRootPath: "/platform/v1/orchestration",
|
||||
}}
|
||||
}
|
||||
|
||||
type OrchestrationDesiredState string
|
||||
|
||||
const (
|
||||
// * active: Creates all the orchestration objects defined in the orchestration.
|
||||
OrchestrationDesiredStateActive OrchestrationDesiredState = "active"
|
||||
// * inactive: Adds the orchestration to Oracle Compute Cloud Service, but does not create any of the orchestration
|
||||
OrchestrationDesiredStateInactive OrchestrationDesiredState = "inactive"
|
||||
// * suspended: Suspends all orchestration objects defined in the orchestration
|
||||
OrchestrationDesiredStateSuspend OrchestrationDesiredState = "suspend"
|
||||
)
|
||||
|
||||
type OrchestrationStatus string
|
||||
|
||||
const (
|
||||
OrchestrationStatusActive OrchestrationStatus = "active"
|
||||
OrchestrationStatusInactive OrchestrationStatus = "inactive"
|
||||
OrchestrationStatusSuspend OrchestrationStatus = "suspend"
|
||||
OrchestrationStatusActivating OrchestrationStatus = "activating"
|
||||
OrchestrationStatusDeleting OrchestrationStatus = "deleting"
|
||||
OrchestrationStatusError OrchestrationStatus = "terminal_error"
|
||||
OrchestrationStatusStopping OrchestrationStatus = "stopping"
|
||||
OrchestrationStatusSuspending OrchestrationStatus = "suspending"
|
||||
OrchestrationStatusStarting OrchestrationStatus = "starting"
|
||||
OrchestrationStatusDeactivating OrchestrationStatus = "deactivating"
|
||||
OrchestrationStatusSuspended OrchestrationStatus = "suspended"
|
||||
)
|
||||
|
||||
type OrchestrationType string
|
||||
|
||||
const (
|
||||
OrchestrationTypeInstance OrchestrationType = "Instance"
|
||||
)
|
||||
|
||||
// OrchestrationInfo describes an existing Orchestration.
|
||||
type Orchestration struct {
|
||||
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
|
||||
Account string `json:"account"`
|
||||
// Description of this orchestration
|
||||
Description string `json:"description"`
|
||||
// The desired_state specified in the orchestration JSON file. A unique identifier for this orchestration.
|
||||
DesiredState OrchestrationDesiredState `json:"desired_state"`
|
||||
// Unique identifier of this orchestration
|
||||
ID string `json:"id"`
|
||||
// The three-part name of the Orchestration (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
// List of orchestration objects
|
||||
Objects []Object `json:"objects"`
|
||||
// Current status of this orchestration
|
||||
Status OrchestrationStatus `json:"status"`
|
||||
// Strings that describe the orchestration and help you identify it.
|
||||
Tags []string `json:"tags"`
|
||||
// Time the orchestration was last audited
|
||||
TimeAudited string `json:"time_audited"`
|
||||
// The time when the orchestration was added to Oracle Compute Cloud Service.
|
||||
TimeCreated string `json:"time_created"`
|
||||
// The time when the orchestration was last updated in Oracle Compute Cloud Service.
|
||||
TimeUpdated string `json:"time_updated"`
|
||||
// Unique Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
// Name of the user who added this orchestration or made the most recent update to this orchestration.
|
||||
User string `json:"user"`
|
||||
// Version of this orchestration. It is automatically generated by the server.
|
||||
Version int `json:"version"`
|
||||
}
|
||||
|
||||
// CreateOrchestrationInput defines an Orchestration to be created.
|
||||
type CreateOrchestrationInput struct {
|
||||
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
|
||||
// Optional
|
||||
Account string `json:"account,omitempty"`
|
||||
// Description of this orchestration
|
||||
// Optional
|
||||
Description string `json:"description,omitempty"`
|
||||
// Specify the desired state of this orchestration: active, inactive, or suspend.
|
||||
// You can manage the state of the orchestration objects by changing the desired state of the orchestration.
|
||||
// * active: Creates all the orchestration objects defined in the orchestration.
|
||||
// * inactive: Adds the orchestration to Oracle Compute Cloud Service, but does not create any of the orchestration
|
||||
// objects defined in the orchestration.
|
||||
// Required
|
||||
DesiredState OrchestrationDesiredState `json:"desired_state"`
|
||||
// The three-part name of the Orchestration (/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 list of objects in the orchestration. An object is the primary building block of an orchestration.
|
||||
// An orchestration can contain up to 100 objects.
|
||||
// Required
|
||||
Objects []Object `json:"objects"`
|
||||
// Strings that describe the orchestration and help you identify it.
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
// Version of this orchestration. It is automatically generated by the server.
|
||||
Version int `json:"version,omitempty"`
|
||||
// Time to wait for an orchestration to be ready
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
|
||||
// Optional
|
||||
Account string `json:"account,omitempty"`
|
||||
// Description of this orchestration
|
||||
// Optional
|
||||
Description string `json:"description,omitempty"`
|
||||
// The desired state of the object
|
||||
// Optional
|
||||
DesiredState OrchestrationDesiredState `json:"desired_state,omitempty"`
|
||||
// Dictionary containing the current state of the object
|
||||
Health Health `json:"health,omitempty"`
|
||||
// A text string describing the object. Labels can't include spaces. In an orchestration, the label for
|
||||
// each object must be unique. Maximum length is 256 characters.
|
||||
// Required
|
||||
Label string `json:"label"`
|
||||
// The four-part name of the object (/Compute-identity_domain/user/orchestration/object). If you don't specify a name
|
||||
// for this object, the name is generated automatically. Object names can contain only alphanumeric characters, hyphens,
|
||||
// underscores, and periods. Object names are case-sensitive. When you specify the object name, ensure that an object of
|
||||
// the same type and with the same name doesn't already exist. If such a object already exists, then another
|
||||
// object of the same type and with the same name won't be created and the existing object won't be updated.
|
||||
// Optional
|
||||
Name string `json:"name,omitempty"`
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the orchestration to which the object belongs.
|
||||
// Required
|
||||
Orchestration string `json:"orchestration"`
|
||||
// Specifies whether the object should persist when the orchestration is suspended. Specify one of the following:
|
||||
// * true: The object persists when the orchestration is suspended.
|
||||
// * false: The object is deleted when the orchestration is suspended.
|
||||
// By default, persistent is set to false. It is recommended that you specify true for storage
|
||||
// volumes and other critical objects. Persistence applies only when you're suspending an orchestration.
|
||||
// When you terminate an orchestration, all the objects defined in it are deleted.
|
||||
// Optional
|
||||
Persistent bool `json:"persistent,omitempty"`
|
||||
// The relationship between the objects that are created by this orchestration. The
|
||||
// only supported relationship is depends, indicating that the specified target objects must be created first.
|
||||
// Note that when recovering from a failure, the orchestration doesn't consider object relationships.
|
||||
// Orchestrations v2 use object references to recover interdependent objects to a healthy state. SeeObject
|
||||
// References and Relationships in Using Oracle Compute Cloud Service (IaaS).
|
||||
Relationship []Object `json:"relationships,omitempty"`
|
||||
// The template attribute defines the properties or characteristics of the Oracle Compute Cloud Service object
|
||||
// that you want to create, as specified by the type attribute.
|
||||
// The fields in the template section vary depending on the specified type. See Orchestration v2 Attributes
|
||||
// Specific to Each Object Type in Using Oracle Compute Cloud Service (IaaS) to determine the parameters that are
|
||||
// specific to each object type that you want to create.
|
||||
// For example, if you want to create a storage volume, the type would be StorageVolume, and the template would include
|
||||
// size and bootable. If you want to create an instance, the type would be Instance, and the template would include
|
||||
// instance-specific attributes, such as imagelist and shape.
|
||||
// Required
|
||||
Template interface{} `json:"template"`
|
||||
// Specify one of the following object types that you want to create.
|
||||
// The only allowed type is Instance
|
||||
// Required
|
||||
Type OrchestrationType `json:"type"`
|
||||
// Version of this object, generated by the server
|
||||
// Optional
|
||||
Version int `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type Health struct {
|
||||
// The status of the object
|
||||
Status OrchestrationStatus `json:"status,omitempty"`
|
||||
// What caused the status of the object
|
||||
Cause string `json:"cause,omitempty"`
|
||||
// The specific details for what happened to the object
|
||||
Detail string `json:"detail,omitempty"`
|
||||
// Any errors associated with creation of the object
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// CreateOrchestration creates a new Orchestration with the given name, key and enabled flag.
|
||||
func (c *OrchestrationsClient) CreateOrchestration(input *CreateOrchestrationInput) (*Orchestration, error) {
|
||||
var createdOrchestration Orchestration
|
||||
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
for _, i := range input.Objects {
|
||||
i.Orchestration = c.getQualifiedName(i.Orchestration)
|
||||
if i.Type == OrchestrationTypeInstance {
|
||||
instanceClient := c.ComputeClient.Instances()
|
||||
instanceInput := i.Template.(*CreateInstanceInput)
|
||||
instanceInput.Name = c.getQualifiedName(instanceInput.Name)
|
||||
|
||||
qualifiedSSHKeys := []string{}
|
||||
for _, key := range instanceInput.SSHKeys {
|
||||
qualifiedSSHKeys = append(qualifiedSSHKeys, c.getQualifiedName(key))
|
||||
}
|
||||
|
||||
instanceInput.SSHKeys = qualifiedSSHKeys
|
||||
|
||||
qualifiedStorageAttachments := []StorageAttachmentInput{}
|
||||
for _, attachment := range instanceInput.Storage {
|
||||
qualifiedStorageAttachments = append(qualifiedStorageAttachments, StorageAttachmentInput{
|
||||
Index: attachment.Index,
|
||||
Volume: c.getQualifiedName(attachment.Volume),
|
||||
})
|
||||
}
|
||||
instanceInput.Storage = qualifiedStorageAttachments
|
||||
|
||||
instanceInput.Networking = instanceClient.qualifyNetworking(instanceInput.Networking)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.createResource(&input, &createdOrchestration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call wait for orchestration ready now, as creating the orchestration is an eventually consistent operation
|
||||
getInput := &GetOrchestrationInput{
|
||||
Name: createdOrchestration.Name,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForOrchestrationActiveTimeout
|
||||
}
|
||||
|
||||
// Wait for orchestration to be ready and return the result
|
||||
// Don't have to unqualify any objects, as the GetOrchestration method will handle that
|
||||
orchestrationInfo, orchestrationError := c.WaitForOrchestrationState(getInput, input.Timeout)
|
||||
if orchestrationError != nil {
|
||||
deleteInput := &DeleteOrchestrationInput{
|
||||
Name: createdOrchestration.Name,
|
||||
}
|
||||
err := c.DeleteOrchestration(deleteInput)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error deleting orchestration %s: %s", getInput.Name, err)
|
||||
}
|
||||
return nil, fmt.Errorf("Error creating orchestration %s: %s", getInput.Name, orchestrationError)
|
||||
}
|
||||
|
||||
return &orchestrationInfo, nil
|
||||
}
|
||||
|
||||
// GetOrchestrationInput describes the Orchestration to get
|
||||
type GetOrchestrationInput struct {
|
||||
// The three-part name of the Orchestration (/Compute-identity_domain/user/object).
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// GetOrchestration retrieves the Orchestration with the given name.
|
||||
func (c *OrchestrationsClient) GetOrchestration(input *GetOrchestrationInput) (*Orchestration, error) {
|
||||
var orchestrationInfo Orchestration
|
||||
if err := c.getResource(input.Name, &orchestrationInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&orchestrationInfo)
|
||||
}
|
||||
|
||||
// UpdateOrchestrationInput defines an Orchestration to be updated
|
||||
type UpdateOrchestrationInput struct {
|
||||
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
|
||||
// Optional
|
||||
Account string `json:"account,omitempty"`
|
||||
// Description of this orchestration
|
||||
// Optional
|
||||
Description string `json:"description,omitempty"`
|
||||
// Specify the desired state of this orchestration: active, inactive, or suspend.
|
||||
// You can manage the state of the orchestration objects by changing the desired state of the orchestration.
|
||||
// * active: Creates all the orchestration objects defined in the orchestration.
|
||||
// * inactive: Adds the orchestration to Oracle Compute Cloud Service, but does not create any of the orchestration
|
||||
// objects defined in the orchestration.
|
||||
// Required
|
||||
DesiredState OrchestrationDesiredState `json:"desired_state"`
|
||||
// The three-part name of the Orchestration (/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 list of objects in the orchestration. An object is the primary building block of an orchestration.
|
||||
// An orchestration can contain up to 100 objects.
|
||||
// Required
|
||||
Objects []Object `json:"objects"`
|
||||
// Strings that describe the orchestration and help you identify it.
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
// Version of this orchestration. It is automatically generated by the server.
|
||||
Version int `json:"version,omitempty"`
|
||||
// Time to wait for an orchestration to be ready
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// UpdateOrchestration updates the orchestration.
|
||||
func (c *OrchestrationsClient) UpdateOrchestration(input *UpdateOrchestrationInput) (*Orchestration, error) {
|
||||
var updatedOrchestration Orchestration
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
for _, i := range input.Objects {
|
||||
i.Orchestration = c.getQualifiedName(i.Orchestration)
|
||||
if i.Type == OrchestrationTypeInstance {
|
||||
instanceInput := i.Template.(map[string]interface{})
|
||||
instanceInput["name"] = c.getQualifiedName(instanceInput["name"].(string))
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.updateResource(input.Name, input, &updatedOrchestration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call wait for orchestration ready now, as creating the orchestration is an eventually consistent operation
|
||||
getInput := &GetOrchestrationInput{
|
||||
Name: updatedOrchestration.Name,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForOrchestrationActiveTimeout
|
||||
}
|
||||
|
||||
// Wait for orchestration to be ready and return the result
|
||||
// Don't have to unqualify any objects, as the GetOrchestration method will handle that
|
||||
orchestrationInfo, orchestrationError := c.WaitForOrchestrationState(getInput, input.Timeout)
|
||||
if orchestrationError != nil {
|
||||
return nil, orchestrationError
|
||||
}
|
||||
|
||||
return &orchestrationInfo, nil
|
||||
}
|
||||
|
||||
// DeleteOrchestrationInput describes the Orchestration to delete
|
||||
type DeleteOrchestrationInput struct {
|
||||
// The three-part name of the Orchestration (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:name`
|
||||
// Timeout for delete request
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// DeleteOrchestration deletes the Orchestration with the given name.
|
||||
func (c *OrchestrationsClient) DeleteOrchestration(input *DeleteOrchestrationInput) error {
|
||||
if err := c.deleteOrchestration(input.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForOrchestrationDeleteTimeout
|
||||
}
|
||||
|
||||
return c.WaitForOrchestrationDeleted(input, input.Timeout)
|
||||
}
|
||||
|
||||
func (c *OrchestrationsClient) success(info *Orchestration) (*Orchestration, error) {
|
||||
c.unqualify(&info.Name)
|
||||
for _, i := range info.Objects {
|
||||
c.unqualify(&i.Orchestration)
|
||||
if OrchestrationType(i.Type) == OrchestrationTypeInstance {
|
||||
instanceInput := i.Template.(map[string]interface{})
|
||||
instanceInput["name"] = c.getUnqualifiedName(instanceInput["name"].(string))
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// WaitForOrchestrationActive waits for an orchestration to be completely initialized and available.
|
||||
func (c *OrchestrationsClient) WaitForOrchestrationState(input *GetOrchestrationInput, timeout time.Duration) (Orchestration, error) {
|
||||
var info *Orchestration
|
||||
var getErr error
|
||||
err := c.client.WaitFor("orchestration to be ready", timeout, func() (bool, error) {
|
||||
info, getErr = c.GetOrchestration(input)
|
||||
if getErr != nil {
|
||||
return false, getErr
|
||||
}
|
||||
c.client.DebugLogString(fmt.Sprintf("Orchestration name is %v, Orchestration info is %+v", info.Name, info))
|
||||
switch s := info.Status; s {
|
||||
case OrchestrationStatusError:
|
||||
// We need to check and see if an object the orchestration is trying to create is giving us an error instead of just the orchestration as a whole.
|
||||
for _, object := range info.Objects {
|
||||
if object.Health.Status == OrchestrationStatusError {
|
||||
return false, fmt.Errorf("Error creating instance %s: %+v", object.Name, object.Health)
|
||||
}
|
||||
}
|
||||
return false, fmt.Errorf("Error initializing orchestration: %+v", info)
|
||||
case OrchestrationStatus(info.DesiredState):
|
||||
c.client.DebugLogString(fmt.Sprintf("Orchestration %s", info.DesiredState))
|
||||
return true, nil
|
||||
case OrchestrationStatusActivating:
|
||||
c.client.DebugLogString("Orchestration activating")
|
||||
return false, nil
|
||||
case OrchestrationStatusStopping:
|
||||
c.client.DebugLogString("Orchestration stopping")
|
||||
return false, nil
|
||||
case OrchestrationStatusSuspending:
|
||||
c.client.DebugLogString("Orchestration suspending")
|
||||
return false, nil
|
||||
case OrchestrationStatusDeactivating:
|
||||
c.client.DebugLogString("Orchestration deactivating")
|
||||
return false, nil
|
||||
case OrchestrationStatusSuspended:
|
||||
c.client.DebugLogString("Orchestration suspended")
|
||||
if info.DesiredState == OrchestrationDesiredStateSuspend {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
default:
|
||||
return false, fmt.Errorf("Unknown orchestration state: %s, erroring", s)
|
||||
}
|
||||
})
|
||||
return *info, err
|
||||
}
|
||||
|
||||
// WaitForOrchestrationDeleted waits for an orchestration to be fully deleted.
|
||||
func (c *OrchestrationsClient) WaitForOrchestrationDeleted(input *DeleteOrchestrationInput, timeout time.Duration) error {
|
||||
return c.client.WaitFor("orchestration to be deleted", timeout, func() (bool, error) {
|
||||
var info Orchestration
|
||||
if err := c.getResource(input.Name, &info); err != nil {
|
||||
if client.WasNotFoundError(err) {
|
||||
// Orchestration could not be found, thus deleted
|
||||
return true, nil
|
||||
}
|
||||
// Some other error occurred trying to get Orchestration, exit
|
||||
return false, err
|
||||
}
|
||||
switch s := info.Status; s {
|
||||
case OrchestrationStatusError:
|
||||
return false, fmt.Errorf("Error stopping orchestration: %+v", info)
|
||||
case OrchestrationStatusStopping:
|
||||
c.client.DebugLogString("Orchestration stopping")
|
||||
return false, nil
|
||||
case OrchestrationStatusDeleting:
|
||||
c.client.DebugLogString("Orchestration deleting")
|
||||
return false, nil
|
||||
case OrchestrationStatusActive:
|
||||
c.client.DebugLogString("Orchestration active")
|
||||
return false, nil
|
||||
default:
|
||||
return false, fmt.Errorf("Unknown orchestration state: %s, erroring", s)
|
||||
}
|
||||
})
|
||||
}
|
153
vendor/github.com/hashicorp/go-oracle-terraform/compute/routes.go
generated
vendored
Normal file
153
vendor/github.com/hashicorp/go-oracle-terraform/compute/routes.go
generated
vendored
Normal 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 *ComputeClient) Routes() *RoutesClient {
|
||||
return &RoutesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
193
vendor/github.com/hashicorp/go-oracle-terraform/compute/sec_rules.go
generated
vendored
Normal file
193
vendor/github.com/hashicorp/go-oracle-terraform/compute/sec_rules.go
generated
vendored
Normal 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 *ComputeClient) SecRules() *SecRulesClient {
|
||||
return &SecRulesClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
150
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_applications.go
generated
vendored
Normal file
150
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_applications.go
generated
vendored
Normal 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 *ComputeClient) SecurityApplications() *SecurityApplicationsClient {
|
||||
return &SecurityApplicationsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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)
|
||||
}
|
95
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_associations.go
generated
vendored
Normal file
95
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_associations.go
generated
vendored
Normal 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 *ComputeClient) SecurityAssociations() *SecurityAssociationsClient {
|
||||
return &SecurityAssociationsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: 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
|
||||
}
|
113
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_ip_lists.go
generated
vendored
Normal file
113
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_ip_lists.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package compute
|
||||
|
||||
// SecurityIPListsClient is a client for the Security IP List functions of the Compute API.
|
||||
type SecurityIPListsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// SecurityIPLists obtains a SecurityIPListsClient which can be used to access to the
|
||||
// Security IP List functions of the Compute API
|
||||
func (c *ComputeClient) SecurityIPLists() *SecurityIPListsClient {
|
||||
return &SecurityIPListsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "security ip list",
|
||||
ContainerPath: "/seciplist/",
|
||||
ResourceRootPath: "/seciplist",
|
||||
}}
|
||||
}
|
||||
|
||||
// SecurityIPListInfo describes an existing security IP list.
|
||||
type SecurityIPListInfo struct {
|
||||
// A description of the security IP list.
|
||||
Description string `json:"description"`
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
// A comma-separated list of the subnets (in CIDR format) or IPv4 addresses for which you want to create this security IP list.
|
||||
SecIPEntries []string `json:"secipentries"`
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
// CreateSecurityIPListInput defines a security IP list to be created.
|
||||
type CreateSecurityIPListInput struct {
|
||||
// A description of the security IP list.
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
// The three-part name of the object (/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"`
|
||||
// A comma-separated list of the subnets (in CIDR format) or IPv4 addresses for which you want to create this security IP list.
|
||||
// Required
|
||||
SecIPEntries []string `json:"secipentries"`
|
||||
}
|
||||
|
||||
// CreateSecurityIPList creates a security IP list with the given name and entries.
|
||||
func (c *SecurityIPListsClient) CreateSecurityIPList(createInput *CreateSecurityIPListInput) (*SecurityIPListInfo, error) {
|
||||
createInput.Name = c.getQualifiedName(createInput.Name)
|
||||
var listInfo SecurityIPListInfo
|
||||
if err := c.createResource(createInput, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// GetSecurityIPListInput describes the Security IP List to obtain
|
||||
type GetSecurityIPListInput struct {
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// GetSecurityIPList gets the security IP list with the given name.
|
||||
func (c *SecurityIPListsClient) GetSecurityIPList(getInput *GetSecurityIPListInput) (*SecurityIPListInfo, error) {
|
||||
var listInfo SecurityIPListInfo
|
||||
if err := c.getResource(getInput.Name, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// UpdateSecurityIPListInput describes the security ip list to update
|
||||
type UpdateSecurityIPListInput struct {
|
||||
// A description of the security IP list.
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
// A comma-separated list of the subnets (in CIDR format) or IPv4 addresses for which you want to create this security IP list.
|
||||
// Required
|
||||
SecIPEntries []string `json:"secipentries"`
|
||||
}
|
||||
|
||||
// UpdateSecurityIPList modifies the entries in the security IP list with the given name.
|
||||
func (c *SecurityIPListsClient) UpdateSecurityIPList(updateInput *UpdateSecurityIPListInput) (*SecurityIPListInfo, error) {
|
||||
updateInput.Name = c.getQualifiedName(updateInput.Name)
|
||||
var listInfo SecurityIPListInfo
|
||||
if err := c.updateResource(updateInput.Name, updateInput, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// DeleteSecurityIPListInput describes the security ip list to delete.
|
||||
type DeleteSecurityIPListInput struct {
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DeleteSecurityIPList deletes the security IP list with the given name.
|
||||
func (c *SecurityIPListsClient) DeleteSecurityIPList(deleteInput *DeleteSecurityIPListInput) error {
|
||||
return c.deleteResource(deleteInput.Name)
|
||||
}
|
||||
|
||||
func (c *SecurityIPListsClient) success(listInfo *SecurityIPListInfo) (*SecurityIPListInfo, error) {
|
||||
c.unqualify(&listInfo.Name)
|
||||
return listInfo, nil
|
||||
}
|
131
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_lists.go
generated
vendored
Normal file
131
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_lists.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
package compute
|
||||
|
||||
// SecurityListsClient is a client for the Security List functions of the Compute API.
|
||||
type SecurityListsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// SecurityLists obtains a SecurityListsClient which can be used to access to the
|
||||
// Security List functions of the Compute API
|
||||
func (c *ComputeClient) SecurityLists() *SecurityListsClient {
|
||||
return &SecurityListsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "security list",
|
||||
ContainerPath: "/seclist/",
|
||||
ResourceRootPath: "/seclist",
|
||||
}}
|
||||
}
|
||||
|
||||
type SecurityListPolicy string
|
||||
|
||||
const (
|
||||
SecurityListPolicyDeny SecurityListPolicy = "deny"
|
||||
SecurityListPolicyReject SecurityListPolicy = "reject"
|
||||
SecurityListPolicyPermit SecurityListPolicy = "permit"
|
||||
)
|
||||
|
||||
// SecurityListInfo describes an existing security list.
|
||||
type SecurityListInfo struct {
|
||||
// Shows the default account for your identity domain.
|
||||
Account string `json:"account"`
|
||||
// A description of the security list.
|
||||
Description string `json:description`
|
||||
// The three-part name of the security list (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
// The policy for outbound traffic from the security list.
|
||||
OutboundCIDRPolicy SecurityListPolicy `json:"outbound_cidr_policy"`
|
||||
// The policy for inbound traffic to the security list
|
||||
Policy SecurityListPolicy `json:"policy"`
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
// CreateSecurityListInput defines a security list to be created.
|
||||
type CreateSecurityListInput struct {
|
||||
// A description of the security list.
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
// The three-part name of the Security List (/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 policy for outbound traffic from the security list.
|
||||
// Optional (defaults to `permit`)
|
||||
OutboundCIDRPolicy SecurityListPolicy `json:"outbound_cidr_policy"`
|
||||
// The policy for inbound traffic to the security list.
|
||||
// Optional (defaults to `deny`)
|
||||
Policy SecurityListPolicy `json:"policy"`
|
||||
}
|
||||
|
||||
// CreateSecurityList creates a new security list with the given name, policy and outbound CIDR policy.
|
||||
func (c *SecurityListsClient) CreateSecurityList(createInput *CreateSecurityListInput) (*SecurityListInfo, error) {
|
||||
createInput.Name = c.getQualifiedName(createInput.Name)
|
||||
var listInfo SecurityListInfo
|
||||
if err := c.createResource(createInput, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// GetSecurityListInput describes the security list you want to get
|
||||
type GetSecurityListInput struct {
|
||||
// The three-part name of the Security List (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// GetSecurityList retrieves the security list with the given name.
|
||||
func (c *SecurityListsClient) GetSecurityList(getInput *GetSecurityListInput) (*SecurityListInfo, error) {
|
||||
var listInfo SecurityListInfo
|
||||
if err := c.getResource(getInput.Name, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// UpdateSecurityListInput defines what to update in a security list
|
||||
type UpdateSecurityListInput struct {
|
||||
// A description of the security list.
|
||||
// Optional
|
||||
Description string `json:description`
|
||||
// The three-part name of the Security List (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
// The policy for outbound traffic from the security list.
|
||||
// Optional (defaults to `permit`)
|
||||
OutboundCIDRPolicy SecurityListPolicy `json:"outbound_cidr_policy"`
|
||||
// The policy for inbound traffic to the security list.
|
||||
// Optional (defaults to `deny`)
|
||||
Policy SecurityListPolicy `json:"policy"`
|
||||
}
|
||||
|
||||
// UpdateSecurityList updates the policy and outbound CIDR pol
|
||||
func (c *SecurityListsClient) UpdateSecurityList(updateInput *UpdateSecurityListInput) (*SecurityListInfo, error) {
|
||||
updateInput.Name = c.getQualifiedName(updateInput.Name)
|
||||
var listInfo SecurityListInfo
|
||||
if err := c.updateResource(updateInput.Name, updateInput, &listInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&listInfo)
|
||||
}
|
||||
|
||||
// DeleteSecurityListInput describes the security list to destroy
|
||||
type DeleteSecurityListInput struct {
|
||||
// The three-part name of the Security List (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// DeleteSecurityList deletes the security list with the given name.
|
||||
func (c *SecurityListsClient) DeleteSecurityList(deleteInput *DeleteSecurityListInput) error {
|
||||
return c.deleteResource(deleteInput.Name)
|
||||
}
|
||||
|
||||
func (c *SecurityListsClient) success(listInfo *SecurityListInfo) (*SecurityListInfo, error) {
|
||||
c.unqualify(&listInfo.Name)
|
||||
return listInfo, nil
|
||||
}
|
187
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_protocols.go
generated
vendored
Normal file
187
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_protocols.go
generated
vendored
Normal file
|
@ -0,0 +1,187 @@
|
|||
package compute
|
||||
|
||||
const (
|
||||
SecurityProtocolDescription = "security protocol"
|
||||
SecurityProtocolContainerPath = "/network/v1/secprotocol/"
|
||||
SecurityProtocolResourcePath = "/network/v1/secprotocol"
|
||||
)
|
||||
|
||||
type SecurityProtocolsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// SecurityProtocols() returns an SecurityProtocolsClient that can be used to access the
|
||||
// necessary CRUD functions for Security Protocols.
|
||||
func (c *ComputeClient) SecurityProtocols() *SecurityProtocolsClient {
|
||||
return &SecurityProtocolsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: SecurityProtocolDescription,
|
||||
ContainerPath: SecurityProtocolContainerPath,
|
||||
ResourceRootPath: SecurityProtocolResourcePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SecurityProtocolInfo contains the exported fields necessary to hold all the information about an
|
||||
// Security Protocol
|
||||
type SecurityProtocolInfo struct {
|
||||
// List of port numbers or port range strings to match the packet's destination port.
|
||||
DstPortSet []string `json:"dstPortSet"`
|
||||
// Protocol used in the data portion of the IP datagram.
|
||||
IPProtocol string `json:"ipProtocol"`
|
||||
// List of port numbers or port range strings to match the packet's source port.
|
||||
SrcPortSet []string `json:"srcPortSet"`
|
||||
// The name of the Security Protocol
|
||||
Name string `json:"name"`
|
||||
// Description of the Security Protocol
|
||||
Description string `json:"description"`
|
||||
// Slice of tags associated with the Security Protocol
|
||||
Tags []string `json:"tags"`
|
||||
// Uniform Resource Identifier for the Security Protocol
|
||||
Uri string `json:"uri"`
|
||||
}
|
||||
|
||||
type CreateSecurityProtocolInput struct {
|
||||
// The name of the Security Protocol 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 SecurityProtocol
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
|
||||
// Enter a list of port numbers or port range strings.
|
||||
//Traffic is enabled by a security rule when a packet's destination port matches the
|
||||
// ports specified here.
|
||||
// For TCP, SCTP, and UDP, each port is a destination transport port, between 0 and 65535,
|
||||
// inclusive. For ICMP, each port is an ICMP type, between 0 and 255, inclusive.
|
||||
// If no destination ports are specified, all destination ports or ICMP types are allowed.
|
||||
// Optional
|
||||
DstPortSet []string `json:"dstPortSet"`
|
||||
|
||||
// The protocol used in the data portion of the IP datagram.
|
||||
// Specify one of the permitted values or enter a number in the range 0–254 to
|
||||
// represent the protocol that you want to specify. See Assigned Internet Protocol Numbers.
|
||||
// Permitted values are: tcp, udp, icmp, igmp, ipip, rdp, esp, ah, gre, icmpv6, ospf, pim, sctp,
|
||||
// mplsip, all.
|
||||
// Traffic is enabled by a security rule when the protocol in the packet matches the
|
||||
// protocol specified here. If no protocol is specified, all protocols are allowed.
|
||||
// Optional
|
||||
IPProtocol string `json:"ipProtocol"`
|
||||
|
||||
// Enter a list of port numbers or port range strings.
|
||||
// Traffic is enabled by a security rule when a packet's source port matches the
|
||||
// ports specified here.
|
||||
// For TCP, SCTP, and UDP, each port is a source transport port,
|
||||
// between 0 and 65535, inclusive.
|
||||
// For ICMP, each port is an ICMP type, between 0 and 255, inclusive.
|
||||
// If no source ports are specified, all source ports or ICMP types are allowed.
|
||||
// Optional
|
||||
SrcPortSet []string `json:"srcPortSet"`
|
||||
|
||||
// String slice of tags to apply to the Security Protocol object
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// Create a new Security Protocol from an SecurityProtocolsClient and an input struct.
|
||||
// Returns a populated Info struct for the Security Protocol, and any errors
|
||||
func (c *SecurityProtocolsClient) CreateSecurityProtocol(input *CreateSecurityProtocolInput) (*SecurityProtocolInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
|
||||
var ipInfo SecurityProtocolInfo
|
||||
if err := c.createResource(&input, &ipInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&ipInfo)
|
||||
}
|
||||
|
||||
type GetSecurityProtocolInput struct {
|
||||
// The name of the Security Protocol to query for. Case-sensitive
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Returns a populated SecurityProtocolInfo struct from an input struct
|
||||
func (c *SecurityProtocolsClient) GetSecurityProtocol(input *GetSecurityProtocolInput) (*SecurityProtocolInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
|
||||
var ipInfo SecurityProtocolInfo
|
||||
if err := c.getResource(input.Name, &ipInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&ipInfo)
|
||||
}
|
||||
|
||||
// UpdateSecurityProtocolInput defines what to update in a security protocol
|
||||
type UpdateSecurityProtocolInput struct {
|
||||
// The name of the Security Protocol 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 SecurityProtocol
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
|
||||
// Enter a list of port numbers or port range strings.
|
||||
//Traffic is enabled by a security rule when a packet's destination port matches the
|
||||
// ports specified here.
|
||||
// For TCP, SCTP, and UDP, each port is a destination transport port, between 0 and 65535,
|
||||
// inclusive. For ICMP, each port is an ICMP type, between 0 and 255, inclusive.
|
||||
// If no destination ports are specified, all destination ports or ICMP types are allowed.
|
||||
DstPortSet []string `json:"dstPortSet"`
|
||||
|
||||
// The protocol used in the data portion of the IP datagram.
|
||||
// Specify one of the permitted values or enter a number in the range 0–254 to
|
||||
// represent the protocol that you want to specify. See Assigned Internet Protocol Numbers.
|
||||
// Permitted values are: tcp, udp, icmp, igmp, ipip, rdp, esp, ah, gre, icmpv6, ospf, pim, sctp,
|
||||
// mplsip, all.
|
||||
// Traffic is enabled by a security rule when the protocol in the packet matches the
|
||||
// protocol specified here. If no protocol is specified, all protocols are allowed.
|
||||
IPProtocol string `json:"ipProtocol"`
|
||||
|
||||
// Enter a list of port numbers or port range strings.
|
||||
// Traffic is enabled by a security rule when a packet's source port matches the
|
||||
// ports specified here.
|
||||
// For TCP, SCTP, and UDP, each port is a source transport port,
|
||||
// between 0 and 65535, inclusive.
|
||||
// For ICMP, each port is an ICMP type, between 0 and 255, inclusive.
|
||||
// If no source ports are specified, all source ports or ICMP types are allowed.
|
||||
SrcPortSet []string `json:"srcPortSet"`
|
||||
|
||||
// String slice of tags to apply to the Security Protocol object
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// UpdateSecurityProtocol update the security protocol
|
||||
func (c *SecurityProtocolsClient) UpdateSecurityProtocol(updateInput *UpdateSecurityProtocolInput) (*SecurityProtocolInfo, error) {
|
||||
updateInput.Name = c.getQualifiedName(updateInput.Name)
|
||||
var ipInfo SecurityProtocolInfo
|
||||
if err := c.updateResource(updateInput.Name, updateInput, &ipInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&ipInfo)
|
||||
}
|
||||
|
||||
type DeleteSecurityProtocolInput struct {
|
||||
// The name of the Security Protocol to query for. Case-sensitive
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *SecurityProtocolsClient) DeleteSecurityProtocol(input *DeleteSecurityProtocolInput) error {
|
||||
return c.deleteResource(input.Name)
|
||||
}
|
||||
|
||||
// Unqualifies any qualified fields in the SecurityProtocolInfo struct
|
||||
func (c *SecurityProtocolsClient) success(info *SecurityProtocolInfo) (*SecurityProtocolInfo, error) {
|
||||
c.unqualify(&info.Name)
|
||||
return info, nil
|
||||
}
|
266
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_rules.go
generated
vendored
Normal file
266
vendor/github.com/hashicorp/go-oracle-terraform/compute/security_rules.go
generated
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
package compute
|
||||
|
||||
const (
|
||||
SecurityRuleDescription = "security rules"
|
||||
SecurityRuleContainerPath = "/network/v1/secrule/"
|
||||
SecurityRuleResourcePath = "/network/v1/secrule"
|
||||
)
|
||||
|
||||
type SecurityRuleClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// SecurityRules() returns an SecurityRulesClient that can be used to access the
|
||||
// necessary CRUD functions for Security Rules.
|
||||
func (c *ComputeClient) SecurityRules() *SecurityRuleClient {
|
||||
return &SecurityRuleClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: SecurityRuleDescription,
|
||||
ContainerPath: SecurityRuleContainerPath,
|
||||
ResourceRootPath: SecurityRuleResourcePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SecurityRuleInfo contains the exported fields necessary to hold all the information about a
|
||||
// Security Rule
|
||||
type SecurityRuleInfo struct {
|
||||
// Name of the ACL that contains this rule.
|
||||
ACL string `json:"acl"`
|
||||
// Description of the Security Rule
|
||||
Description string `json:"description"`
|
||||
// List of IP address prefix set names to match the packet's destination IP address.
|
||||
DstIpAddressPrefixSets []string `json:"dstIpAddressPrefixSets"`
|
||||
// Name of virtual NIC set containing the packet's destination virtual NIC.
|
||||
DstVnicSet string `json:"dstVnicSet"`
|
||||
// Allows the security rule to be disabled.
|
||||
Enabled bool `json:"enabledFlag"`
|
||||
// Direction of the flow; Can be "egress" or "ingress".
|
||||
FlowDirection string `json:"FlowDirection"`
|
||||
// The name of the Security Rule
|
||||
Name string `json:"name"`
|
||||
// List of security protocol names to match the packet's protocol and port.
|
||||
SecProtocols []string `json:"secProtocols"`
|
||||
// List of multipart names of IP address prefix set to match the packet's source IP address.
|
||||
SrcIpAddressPrefixSets []string `json:"srcIpAddressPrefixSets"`
|
||||
// Name of virtual NIC set containing the packet's source virtual NIC.
|
||||
SrcVnicSet string `json:"srcVnicSet"`
|
||||
// Slice of tags associated with the Security Rule
|
||||
Tags []string `json:"tags"`
|
||||
// Uniform Resource Identifier for the Security Rule
|
||||
Uri string `json:"uri"`
|
||||
}
|
||||
|
||||
type CreateSecurityRuleInput struct {
|
||||
//Select the name of the access control list (ACL) that you want to add this
|
||||
// security rule to. Security rules are applied to vNIC sets by using ACLs.
|
||||
// Optional
|
||||
ACL string `json:"acl,omitempty"`
|
||||
|
||||
// Description of the Security Rule
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
|
||||
// A list of IP address prefix sets to which you want to permit traffic.
|
||||
// Only packets to IP addresses in the specified IP address prefix sets are permitted.
|
||||
// When no destination IP address prefix sets are specified, traffic to any
|
||||
// IP address is permitted.
|
||||
// Optional
|
||||
DstIpAddressPrefixSets []string `json:"dstIpAddressPrefixSets"`
|
||||
|
||||
// The vNICset to which you want to permit traffic. Only packets to vNICs in the
|
||||
// specified vNICset are permitted. When no destination vNICset is specified, traffic
|
||||
// to any vNIC is permitted.
|
||||
// Optional
|
||||
DstVnicSet string `json:"dstVnicSet,omitempty"`
|
||||
|
||||
// Allows the security rule to be enabled or disabled. This parameter is set to
|
||||
// true by default. Specify false to disable the security rule.
|
||||
// Optional
|
||||
Enabled bool `json:"enabledFlag"`
|
||||
|
||||
// Specify the direction of flow of traffic, which is relative to the instances,
|
||||
// for this security rule. Allowed values are ingress or egress.
|
||||
// An ingress packet is a packet received by a virtual NIC, for example from
|
||||
// another virtual NIC or from the public Internet.
|
||||
// An egress packet is a packet sent by a virtual NIC, for example to another
|
||||
// virtual NIC or to the public Internet.
|
||||
// Required
|
||||
FlowDirection string `json:"flowDirection"`
|
||||
|
||||
// The name of the Security Rule
|
||||
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods.
|
||||
// Object names are case-sensitive. When you specify the object name, ensure that an object
|
||||
// of the same type and with the same name doesn't already exist.
|
||||
// If such an object already exists, another object of the same type and with the same name won't
|
||||
// be created and the existing object won't be updated.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
|
||||
// A list of security protocols for which you want to permit traffic. Only packets that
|
||||
// match the specified protocols and ports are permitted. When no security protocols are
|
||||
// specified, traffic using any protocol over any port is permitted.
|
||||
// Optional
|
||||
SecProtocols []string `json:"secProtocols"`
|
||||
|
||||
// A list of IP address prefix sets from which you want to permit traffic. Only packets
|
||||
// from IP addresses in the specified IP address prefix sets are permitted. When no source
|
||||
// IP address prefix sets are specified, traffic from any IP address is permitted.
|
||||
// Optional
|
||||
SrcIpAddressPrefixSets []string `json:"srcIpAddressPrefixSets"`
|
||||
|
||||
// The vNICset from which you want to permit traffic. Only packets from vNICs in the
|
||||
// specified vNICset are permitted. When no source vNICset is specified, traffic from any
|
||||
// vNIC is permitted.
|
||||
// Optional
|
||||
SrcVnicSet string `json:"srcVnicSet,omitempty"`
|
||||
|
||||
// Strings that you can use to tag the security rule.
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// Create a new Security Rule from an SecurityRuleClient and an input struct.
|
||||
// Returns a populated Info struct for the Security Rule, and any errors
|
||||
func (c *SecurityRuleClient) CreateSecurityRule(input *CreateSecurityRuleInput) (*SecurityRuleInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
input.ACL = c.getQualifiedName(input.ACL)
|
||||
input.SrcVnicSet = c.getQualifiedName(input.SrcVnicSet)
|
||||
input.DstVnicSet = c.getQualifiedName(input.DstVnicSet)
|
||||
input.SrcIpAddressPrefixSets = c.getQualifiedList(input.SrcIpAddressPrefixSets)
|
||||
input.DstIpAddressPrefixSets = c.getQualifiedList(input.DstIpAddressPrefixSets)
|
||||
input.SecProtocols = c.getQualifiedList(input.SecProtocols)
|
||||
|
||||
var securityRuleInfo SecurityRuleInfo
|
||||
if err := c.createResource(&input, &securityRuleInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&securityRuleInfo)
|
||||
}
|
||||
|
||||
type GetSecurityRuleInput struct {
|
||||
// The name of the Security Rule to query for. Case-sensitive
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Returns a populated SecurityRuleInfo struct from an input struct
|
||||
func (c *SecurityRuleClient) GetSecurityRule(input *GetSecurityRuleInput) (*SecurityRuleInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
|
||||
var securityRuleInfo SecurityRuleInfo
|
||||
if err := c.getResource(input.Name, &securityRuleInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&securityRuleInfo)
|
||||
}
|
||||
|
||||
// UpdateSecurityRuleInput describes a secruity rule to update
|
||||
type UpdateSecurityRuleInput struct {
|
||||
//Select the name of the access control list (ACL) that you want to add this
|
||||
// security rule to. Security rules are applied to vNIC sets by using ACLs.
|
||||
// Optional
|
||||
ACL string `json:"acl,omitempty"`
|
||||
|
||||
// Description of the Security Rule
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
|
||||
// A list of IP address prefix sets to which you want to permit traffic.
|
||||
// Only packets to IP addresses in the specified IP address prefix sets are permitted.
|
||||
// When no destination IP address prefix sets are specified, traffic to any
|
||||
// IP address is permitted.
|
||||
// Optional
|
||||
DstIpAddressPrefixSets []string `json:"dstIpAddressPrefixSets"`
|
||||
|
||||
// The vNICset to which you want to permit traffic. Only packets to vNICs in the
|
||||
// specified vNICset are permitted. When no destination vNICset is specified, traffic
|
||||
// to any vNIC is permitted.
|
||||
// Optional
|
||||
DstVnicSet string `json:"dstVnicSet,omitempty"`
|
||||
|
||||
// Allows the security rule to be enabled or disabled. This parameter is set to
|
||||
// true by default. Specify false to disable the security rule.
|
||||
// Optional
|
||||
Enabled bool `json:"enabledFlag"`
|
||||
|
||||
// Specify the direction of flow of traffic, which is relative to the instances,
|
||||
// for this security rule. Allowed values are ingress or egress.
|
||||
// An ingress packet is a packet received by a virtual NIC, for example from
|
||||
// another virtual NIC or from the public Internet.
|
||||
// An egress packet is a packet sent by a virtual NIC, for example to another
|
||||
// virtual NIC or to the public Internet.
|
||||
// Required
|
||||
FlowDirection string `json:"flowDirection"`
|
||||
|
||||
// The name of the Security Rule
|
||||
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods.
|
||||
// Object names are case-sensitive. When you specify the object name, ensure that an object
|
||||
// of the same type and with the same name doesn't already exist.
|
||||
// If such an object already exists, another object of the same type and with the same name won't
|
||||
// be created and the existing object won't be updated.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
|
||||
// A list of security protocols for which you want to permit traffic. Only packets that
|
||||
// match the specified protocols and ports are permitted. When no security protocols are
|
||||
// specified, traffic using any protocol over any port is permitted.
|
||||
// Optional
|
||||
SecProtocols []string `json:"secProtocols"`
|
||||
|
||||
// A list of IP address prefix sets from which you want to permit traffic. Only packets
|
||||
// from IP addresses in the specified IP address prefix sets are permitted. When no source
|
||||
// IP address prefix sets are specified, traffic from any IP address is permitted.
|
||||
// Optional
|
||||
SrcIpAddressPrefixSets []string `json:"srcIpAddressPrefixSets"`
|
||||
|
||||
// The vNICset from which you want to permit traffic. Only packets from vNICs in the
|
||||
// specified vNICset are permitted. When no source vNICset is specified, traffic from any
|
||||
// vNIC is permitted.
|
||||
// Optional
|
||||
SrcVnicSet string `json:"srcVnicSet,omitempty"`
|
||||
|
||||
// Strings that you can use to tag the security rule.
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// UpdateSecRule modifies the properties of the sec rule with the given name.
|
||||
func (c *SecurityRuleClient) UpdateSecurityRule(updateInput *UpdateSecurityRuleInput) (*SecurityRuleInfo, error) {
|
||||
updateInput.Name = c.getQualifiedName(updateInput.Name)
|
||||
updateInput.ACL = c.getQualifiedName(updateInput.ACL)
|
||||
updateInput.SrcVnicSet = c.getQualifiedName(updateInput.SrcVnicSet)
|
||||
updateInput.DstVnicSet = c.getQualifiedName(updateInput.DstVnicSet)
|
||||
updateInput.SrcIpAddressPrefixSets = c.getQualifiedList(updateInput.SrcIpAddressPrefixSets)
|
||||
updateInput.DstIpAddressPrefixSets = c.getQualifiedList(updateInput.DstIpAddressPrefixSets)
|
||||
updateInput.SecProtocols = c.getQualifiedList(updateInput.SecProtocols)
|
||||
|
||||
var securityRuleInfo SecurityRuleInfo
|
||||
if err := c.updateResource(updateInput.Name, updateInput, &securityRuleInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&securityRuleInfo)
|
||||
}
|
||||
|
||||
type DeleteSecurityRuleInput struct {
|
||||
// The name of the Security Rule to query for. Case-sensitive
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *SecurityRuleClient) DeleteSecurityRule(input *DeleteSecurityRuleInput) error {
|
||||
return c.deleteResource(input.Name)
|
||||
}
|
||||
|
||||
// Unqualifies any qualified fields in the IPNetworkExchangeInfo struct
|
||||
func (c *SecurityRuleClient) success(info *SecurityRuleInfo) (*SecurityRuleInfo, error) {
|
||||
c.unqualify(&info.Name, &info.ACL, &info.SrcVnicSet, &info.DstVnicSet)
|
||||
info.SrcIpAddressPrefixSets = c.getUnqualifiedList(info.SrcIpAddressPrefixSets)
|
||||
info.DstIpAddressPrefixSets = c.getUnqualifiedList(info.DstIpAddressPrefixSets)
|
||||
info.SecProtocols = c.getUnqualifiedList(info.SecProtocols)
|
||||
return info, nil
|
||||
}
|
242
vendor/github.com/hashicorp/go-oracle-terraform/compute/snapshots.go
generated
vendored
Normal file
242
vendor/github.com/hashicorp/go-oracle-terraform/compute/snapshots.go
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const WaitForSnapshotCompleteTimeout = time.Duration(600 * time.Second)
|
||||
|
||||
// SnapshotsClient is a client for the Snapshot functions of the Compute API.
|
||||
type SnapshotsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// Snapshots obtains an SnapshotsClient which can be used to access to the
|
||||
// Snapshot functions of the Compute API
|
||||
func (c *ComputeClient) Snapshots() *SnapshotsClient {
|
||||
return &SnapshotsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "Snapshot",
|
||||
ContainerPath: "/snapshot/",
|
||||
ResourceRootPath: "/snapshot",
|
||||
}}
|
||||
}
|
||||
|
||||
type SnapshotState string
|
||||
|
||||
const (
|
||||
SnapshotActive SnapshotState = "active"
|
||||
SnapshotComplete SnapshotState = "complete"
|
||||
SnapshotQueued SnapshotState = "queued"
|
||||
SnapshotError SnapshotState = "error"
|
||||
)
|
||||
|
||||
type SnapshotDelay string
|
||||
|
||||
const (
|
||||
SnapshotDelayShutdown SnapshotDelay = "shutdown"
|
||||
)
|
||||
|
||||
// SnapshotInfo describes an existing Snapshot.
|
||||
type Snapshot struct {
|
||||
// Shows the default account for your identity domain.
|
||||
Account string `json:"account"`
|
||||
// Timestamp when this request was created.
|
||||
CreationTime string `json:"creation_time"`
|
||||
// Snapshot of the instance is not taken immediately.
|
||||
Delay SnapshotDelay `json:"delay"`
|
||||
// A description of the reason this request entered "error" state.
|
||||
ErrorReason string `json:"error_reason"`
|
||||
// Name of the instance
|
||||
Instance string `json:"instance"`
|
||||
// Name of the machine image generated from the instance snapshot request.
|
||||
MachineImage string `json:"machineimage"`
|
||||
// Name of the instance snapshot request.
|
||||
Name string `json:"name"`
|
||||
// Not used
|
||||
Quota string `json:"quota"`
|
||||
// The state of the request.
|
||||
State SnapshotState `json:"state"`
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
// CreateSnapshotInput defines an Snapshot to be created.
|
||||
type CreateSnapshotInput struct {
|
||||
// The name of the account that contains the credentials and access details of
|
||||
// Oracle Storage Cloud Service. The machine image file is uploaded to the Oracle
|
||||
// Storage Cloud Service account that you specify.
|
||||
// Optional
|
||||
Account string `json:"account,omitempty"`
|
||||
// Use this option when you want to preserve the custom changes you have made
|
||||
// to an instance before deleting the instance. The only permitted value is shutdown.
|
||||
// Snapshot of the instance is not taken immediately. It creates a machine image which
|
||||
// preserves the changes you have made to the instance, and then the instance is deleted.
|
||||
// Note: This option has no effect if you shutdown the instance from inside it. Any pending
|
||||
// snapshot request on that instance goes into error state. You must delete the instance
|
||||
// (DELETE /instance/{name}).
|
||||
// Optional
|
||||
Delay SnapshotDelay `json:"delay,omitempty"`
|
||||
// Name of the instance that you want to clone.
|
||||
// Required
|
||||
Instance string `json:"instance"`
|
||||
// Specify the name of the machine image created by the snapshot request.
|
||||
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods.
|
||||
// Object names are case-sensitive.
|
||||
// If you don't specify a name for this object, then the name is generated automatically.
|
||||
// Optional
|
||||
MachineImage string `json:"machineimage,omitempty"`
|
||||
// Time to wait for snapshot to be completed
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// CreateSnapshot creates a new Snapshot
|
||||
func (c *SnapshotsClient) CreateSnapshot(input *CreateSnapshotInput) (*Snapshot, error) {
|
||||
input.Account = c.getQualifiedACMEName(input.Account)
|
||||
input.Instance = c.getQualifiedName(input.Instance)
|
||||
input.MachineImage = c.getQualifiedName(input.MachineImage)
|
||||
|
||||
var snapshotInfo Snapshot
|
||||
if err := c.createResource(&input, &snapshotInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call wait for snapshot complete now, as creating the snashot is an eventually consistent operation
|
||||
getInput := &GetSnapshotInput{
|
||||
Name: snapshotInfo.Name,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForSnapshotCompleteTimeout
|
||||
}
|
||||
|
||||
// Wait for snapshot to be complete and return the result
|
||||
return c.WaitForSnapshotComplete(getInput, input.Timeout)
|
||||
}
|
||||
|
||||
// GetSnapshotInput describes the snapshot to get
|
||||
type GetSnapshotInput struct {
|
||||
// The name of the Snapshot
|
||||
// Required
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// GetSnapshot retrieves the Snapshot with the given name.
|
||||
func (c *SnapshotsClient) GetSnapshot(getInput *GetSnapshotInput) (*Snapshot, error) {
|
||||
getInput.Name = c.getQualifiedName(getInput.Name)
|
||||
var snapshotInfo Snapshot
|
||||
if err := c.getResource(getInput.Name, &snapshotInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&snapshotInfo)
|
||||
}
|
||||
|
||||
// DeleteSnapshotInput describes the snapshot to delete
|
||||
type DeleteSnapshotInput struct {
|
||||
// The name of the Snapshot
|
||||
// Required
|
||||
Snapshot string
|
||||
// The name of the machine image
|
||||
// Required
|
||||
MachineImage string
|
||||
// Time to wait for snapshot to be deleted
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// DeleteSnapshot deletes the Snapshot with the given name.
|
||||
// A machine image gets created with the associated snapshot and needs to be deleted as well.
|
||||
func (c *SnapshotsClient) DeleteSnapshot(machineImagesClient *MachineImagesClient, input *DeleteSnapshotInput) error {
|
||||
// Wait for snapshot complete in case delay is active and the corresponding instance needs to be deleted first
|
||||
getInput := &GetSnapshotInput{
|
||||
Name: input.Snapshot,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForSnapshotCompleteTimeout
|
||||
}
|
||||
|
||||
if _, err := c.WaitForSnapshotComplete(getInput, input.Timeout); err != nil {
|
||||
return fmt.Errorf("Could not delete snapshot: %s", err)
|
||||
}
|
||||
|
||||
if err := c.deleteResource(input.Snapshot); err != nil {
|
||||
return fmt.Errorf("Could not delete snapshot: %s", err)
|
||||
}
|
||||
|
||||
deleteMachineImageRequest := &DeleteMachineImageInput{
|
||||
Name: input.MachineImage,
|
||||
}
|
||||
if err := machineImagesClient.DeleteMachineImage(deleteMachineImageRequest); err != nil {
|
||||
return fmt.Errorf("Could not delete machine image associated with snapshot: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteSnapshot deletes the Snapshot with the given name.
|
||||
// A machine image gets created with the associated snapshot is not deleted
|
||||
// by this method.
|
||||
func (c *SnapshotsClient) DeleteSnapshotResourceOnly(input *DeleteSnapshotInput) error {
|
||||
// Wait for snapshot complete in case delay is active and the corresponding
|
||||
// instance needs to be deleted first
|
||||
getInput := &GetSnapshotInput{
|
||||
Name: input.Snapshot,
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForSnapshotCompleteTimeout
|
||||
}
|
||||
|
||||
if _, err := c.WaitForSnapshotComplete(getInput, input.Timeout); err != nil {
|
||||
return fmt.Errorf("Could not delete snapshot: %s", err)
|
||||
}
|
||||
|
||||
if err := c.deleteResource(input.Snapshot); err != nil {
|
||||
return fmt.Errorf("Could not delete snapshot: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForSnapshotComplete waits for an snapshot to be completely initialized and available.
|
||||
func (c *SnapshotsClient) WaitForSnapshotComplete(input *GetSnapshotInput, timeout time.Duration) (*Snapshot, error) {
|
||||
var info *Snapshot
|
||||
var getErr error
|
||||
err := c.client.WaitFor("snapshot to be complete", timeout, func() (bool, error) {
|
||||
info, getErr = c.GetSnapshot(input)
|
||||
if getErr != nil {
|
||||
return false, getErr
|
||||
}
|
||||
switch s := info.State; s {
|
||||
case SnapshotError:
|
||||
return false, fmt.Errorf("Error initializing snapshot: %s", info.ErrorReason)
|
||||
case SnapshotComplete:
|
||||
c.client.DebugLogString("Snapshot Complete")
|
||||
return true, nil
|
||||
case SnapshotQueued:
|
||||
c.client.DebugLogString("Snapshot Queuing")
|
||||
return false, nil
|
||||
case SnapshotActive:
|
||||
c.client.DebugLogString("Snapshot Active")
|
||||
if info.Delay == SnapshotDelayShutdown {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
default:
|
||||
c.client.DebugLogString(fmt.Sprintf("Unknown snapshot state: %s, waiting", s))
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (c *SnapshotsClient) success(snapshotInfo *Snapshot) (*Snapshot, error) {
|
||||
c.unqualify(&snapshotInfo.Account)
|
||||
c.unqualify(&snapshotInfo.Instance)
|
||||
c.unqualify(&snapshotInfo.MachineImage)
|
||||
c.unqualify(&snapshotInfo.Name)
|
||||
return snapshotInfo, nil
|
||||
}
|
124
vendor/github.com/hashicorp/go-oracle-terraform/compute/ssh_keys.go
generated
vendored
Normal file
124
vendor/github.com/hashicorp/go-oracle-terraform/compute/ssh_keys.go
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
package compute
|
||||
|
||||
// SSHKeysClient is a client for the SSH key functions of the Compute API.
|
||||
type SSHKeysClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// SSHKeys obtains an SSHKeysClient which can be used to access to the
|
||||
// SSH key functions of the Compute API
|
||||
func (c *ComputeClient) SSHKeys() *SSHKeysClient {
|
||||
return &SSHKeysClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "SSH key",
|
||||
ContainerPath: "/sshkey/",
|
||||
ResourceRootPath: "/sshkey",
|
||||
}}
|
||||
}
|
||||
|
||||
// SSHKeyInfo describes an existing SSH key.
|
||||
type SSHKey struct {
|
||||
// Indicates whether the key is enabled (true) or disabled.
|
||||
Enabled bool `json:"enabled"`
|
||||
// The SSH public key value.
|
||||
Key string `json:"key"`
|
||||
// The three-part name of the SSH Key (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
// Unique Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
||||
// CreateSSHKeyInput defines an SSH key to be created.
|
||||
type CreateSSHKeyInput struct {
|
||||
// The three-part name of the SSH Key (/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 SSH public key value.
|
||||
// Required
|
||||
Key string `json:"key"`
|
||||
// Indicates whether the key must be enabled (default) or disabled. Note that disabled keys cannot be associated with instances.
|
||||
// To explicitly enable the key, specify true. To disable the key, specify false.
|
||||
// Optional
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// CreateSSHKey creates a new SSH key with the given name, key and enabled flag.
|
||||
func (c *SSHKeysClient) CreateSSHKey(createInput *CreateSSHKeyInput) (*SSHKey, error) {
|
||||
var keyInfo SSHKey
|
||||
// We have to update after create to get the full ssh key into opc
|
||||
updateSSHKeyInput := UpdateSSHKeyInput{
|
||||
Name: createInput.Name,
|
||||
Key: createInput.Key,
|
||||
Enabled: createInput.Enabled,
|
||||
}
|
||||
|
||||
createInput.Name = c.getQualifiedName(createInput.Name)
|
||||
if err := c.createResource(&createInput, &keyInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err := c.UpdateSSHKey(&updateSSHKeyInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&keyInfo)
|
||||
}
|
||||
|
||||
// GetSSHKeyInput describes the ssh key to get
|
||||
type GetSSHKeyInput struct {
|
||||
// The three-part name of the SSH Key (/Compute-identity_domain/user/object).
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// GetSSHKey retrieves the SSH key with the given name.
|
||||
func (c *SSHKeysClient) GetSSHKey(getInput *GetSSHKeyInput) (*SSHKey, error) {
|
||||
var keyInfo SSHKey
|
||||
if err := c.getResource(getInput.Name, &keyInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&keyInfo)
|
||||
}
|
||||
|
||||
// UpdateSSHKeyInput defines an SSH key to be updated
|
||||
type UpdateSSHKeyInput struct {
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
// The SSH public key value.
|
||||
// Required
|
||||
Key string `json:"key"`
|
||||
// Indicates whether the key must be enabled (default) or disabled. Note that disabled keys cannot be associated with instances.
|
||||
// To explicitly enable the key, specify true. To disable the key, specify false.
|
||||
// Optional
|
||||
// TODO/NOTE: isn't this required?
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// UpdateSSHKey updates the key and enabled flag of the SSH key with the given name.
|
||||
func (c *SSHKeysClient) UpdateSSHKey(updateInput *UpdateSSHKeyInput) (*SSHKey, error) {
|
||||
var keyInfo SSHKey
|
||||
updateInput.Name = c.getQualifiedName(updateInput.Name)
|
||||
if err := c.updateResource(updateInput.Name, updateInput, &keyInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.success(&keyInfo)
|
||||
}
|
||||
|
||||
// DeleteKeyInput describes the ssh key to delete
|
||||
type DeleteSSHKeyInput struct {
|
||||
// The three-part name of the SSH Key (/Compute-identity_domain/user/object).
|
||||
Name string `json:name`
|
||||
}
|
||||
|
||||
// DeleteSSHKey deletes the SSH key with the given name.
|
||||
func (c *SSHKeysClient) DeleteSSHKey(deleteInput *DeleteSSHKeyInput) error {
|
||||
return c.deleteResource(deleteInput.Name)
|
||||
}
|
||||
|
||||
func (c *SSHKeysClient) success(keyInfo *SSHKey) (*SSHKey, error) {
|
||||
c.unqualify(&keyInfo.Name)
|
||||
return keyInfo, nil
|
||||
}
|
178
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_attachments.go
generated
vendored
Normal file
178
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_attachments.go
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
)
|
||||
|
||||
const WaitForVolumeAttachmentDeleteTimeout = time.Duration(30 * time.Second)
|
||||
const WaitForVolumeAttachmentReadyTimeout = time.Duration(30 * time.Second)
|
||||
|
||||
// StorageAttachmentsClient is a client for the Storage Attachment functions of the Compute API.
|
||||
type StorageAttachmentsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// StorageAttachments obtains a StorageAttachmentsClient which can be used to access to the
|
||||
// Storage Attachment functions of the Compute API
|
||||
func (c *ComputeClient) StorageAttachments() *StorageAttachmentsClient {
|
||||
return &StorageAttachmentsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "storage volume attachment",
|
||||
ContainerPath: "/storage/attachment/",
|
||||
ResourceRootPath: "/storage/attachment",
|
||||
}}
|
||||
}
|
||||
|
||||
type StorageAttachmentState string
|
||||
|
||||
const (
|
||||
Attaching StorageAttachmentState = "attaching"
|
||||
Attached StorageAttachmentState = "attached"
|
||||
Detaching StorageAttachmentState = "detaching"
|
||||
Unavailable StorageAttachmentState = "unavailable"
|
||||
Unknown StorageAttachmentState = "unknown"
|
||||
)
|
||||
|
||||
// StorageAttachmentInfo describes an existing storage attachment.
|
||||
type StorageAttachmentInfo struct {
|
||||
// Name of this attachment, generated by the server.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Index number for the volume. The allowed range is 1-10
|
||||
// An attachment with index 1 is exposed to the instance as /dev/xvdb, an attachment with index 2 is exposed as /dev/xvdc, and so on.
|
||||
Index int `json:"index"`
|
||||
|
||||
// Multipart name of the instance attached to the storage volume.
|
||||
InstanceName string `json:"instance_name"`
|
||||
|
||||
// Multipart name of the volume attached to the instance.
|
||||
StorageVolumeName string `json:"storage_volume_name"`
|
||||
|
||||
// The State of the Storage Attachment
|
||||
State StorageAttachmentState `json:"state"`
|
||||
}
|
||||
|
||||
func (c *StorageAttachmentsClient) success(attachmentInfo *StorageAttachmentInfo) (*StorageAttachmentInfo, error) {
|
||||
c.unqualify(&attachmentInfo.Name, &attachmentInfo.InstanceName, &attachmentInfo.StorageVolumeName)
|
||||
return attachmentInfo, nil
|
||||
}
|
||||
|
||||
type CreateStorageAttachmentInput struct {
|
||||
// Index number for the volume. The allowed range is 1-10
|
||||
// An attachment with index 1 is exposed to the instance as /dev/xvdb, an attachment with index 2 is exposed as /dev/xvdc, and so on.
|
||||
// Required.
|
||||
Index int `json:"index"`
|
||||
|
||||
// Multipart name of the instance to which you want to attach the volume.
|
||||
// Required.
|
||||
InstanceName string `json:"instance_name"`
|
||||
|
||||
// Multipart name of the volume that you want to attach.
|
||||
// Required.
|
||||
StorageVolumeName string `json:"storage_volume_name"`
|
||||
|
||||
// Time to wait for storage volume attachment
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// CreateStorageAttachment creates a storage attachment attaching the given volume to the given instance at the given index.
|
||||
func (c *StorageAttachmentsClient) CreateStorageAttachment(input *CreateStorageAttachmentInput) (*StorageAttachmentInfo, error) {
|
||||
input.InstanceName = c.getQualifiedName(input.InstanceName)
|
||||
|
||||
var attachmentInfo *StorageAttachmentInfo
|
||||
if err := c.createResource(&input, &attachmentInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForVolumeAttachmentReadyTimeout
|
||||
}
|
||||
|
||||
return c.waitForStorageAttachmentToFullyAttach(attachmentInfo.Name, input.Timeout)
|
||||
}
|
||||
|
||||
// DeleteStorageAttachmentInput represents the body of an API request to delete a Storage Attachment.
|
||||
type DeleteStorageAttachmentInput struct {
|
||||
// The three-part name of the Storage Attachment (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
|
||||
// Time to wait for storage volume snapshot
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// DeleteStorageAttachment deletes the storage attachment with the given name.
|
||||
func (c *StorageAttachmentsClient) DeleteStorageAttachment(input *DeleteStorageAttachmentInput) error {
|
||||
if err := c.deleteResource(input.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForVolumeAttachmentDeleteTimeout
|
||||
}
|
||||
|
||||
return c.waitForStorageAttachmentToBeDeleted(input.Name, input.Timeout)
|
||||
}
|
||||
|
||||
// GetStorageAttachmentInput represents the body of an API request to obtain a Storage Attachment.
|
||||
type GetStorageAttachmentInput struct {
|
||||
// The three-part name of the Storage Attachment (/Compute-identity_domain/user/object).
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// GetStorageAttachment retrieves the storage attachment with the given name.
|
||||
func (c *StorageAttachmentsClient) GetStorageAttachment(input *GetStorageAttachmentInput) (*StorageAttachmentInfo, error) {
|
||||
var attachmentInfo *StorageAttachmentInfo
|
||||
if err := c.getResource(input.Name, &attachmentInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(attachmentInfo)
|
||||
}
|
||||
|
||||
// waitForStorageAttachmentToFullyAttach waits for the storage attachment with the given name to be fully attached, or times out.
|
||||
func (c *StorageAttachmentsClient) waitForStorageAttachmentToFullyAttach(name string, timeout time.Duration) (*StorageAttachmentInfo, error) {
|
||||
var waitResult *StorageAttachmentInfo
|
||||
|
||||
err := c.client.WaitFor("storage attachment to be attached", timeout, func() (bool, error) {
|
||||
input := &GetStorageAttachmentInput{
|
||||
Name: name,
|
||||
}
|
||||
info, err := c.GetStorageAttachment(input)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if info != nil {
|
||||
if info.State == Attached {
|
||||
waitResult = info
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
|
||||
return waitResult, err
|
||||
}
|
||||
|
||||
// waitForStorageAttachmentToBeDeleted waits for the storage attachment with the given name to be fully deleted, or times out.
|
||||
func (c *StorageAttachmentsClient) waitForStorageAttachmentToBeDeleted(name string, timeout time.Duration) error {
|
||||
return c.client.WaitFor("storage attachment to be deleted", timeout, func() (bool, error) {
|
||||
input := &GetStorageAttachmentInput{
|
||||
Name: name,
|
||||
}
|
||||
_, err := c.GetStorageAttachment(input)
|
||||
if err != nil {
|
||||
if client.WasNotFoundError(err) {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
251
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go
generated
vendored
Normal file
251
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volume_snapshots.go
generated
vendored
Normal file
|
@ -0,0 +1,251 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
)
|
||||
|
||||
const (
|
||||
StorageVolumeSnapshotDescription = "storage volume snapshot"
|
||||
StorageVolumeSnapshotContainerPath = "/storage/snapshot/"
|
||||
StorageVolumeSnapshotResourcePath = "/storage/snapshot"
|
||||
|
||||
WaitForSnapshotCreateTimeout = time.Duration(2400 * time.Second)
|
||||
WaitForSnapshotDeleteTimeout = time.Duration(1500 * time.Second)
|
||||
|
||||
// Collocated Snapshot Property
|
||||
SnapshotPropertyCollocated = "/oracle/private/storage/snapshot/collocated"
|
||||
)
|
||||
|
||||
// StorageVolumeSnapshotClient is a client for the Storage Volume Snapshot functions of the Compute API.
|
||||
type StorageVolumeSnapshotClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
func (c *ComputeClient) StorageVolumeSnapshots() *StorageVolumeSnapshotClient {
|
||||
return &StorageVolumeSnapshotClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: StorageVolumeSnapshotDescription,
|
||||
ContainerPath: StorageVolumeSnapshotContainerPath,
|
||||
ResourceRootPath: StorageVolumeSnapshotResourcePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// StorageVolumeSnapshotInfo represents the information retrieved from the service about a storage volume snapshot
|
||||
type StorageVolumeSnapshotInfo struct {
|
||||
// Account to use for snapshots
|
||||
Account string `json:"account"`
|
||||
|
||||
// Description of the snapshot
|
||||
Description string `json:"description"`
|
||||
|
||||
// The name of the machine image that's used in the boot volume from which this snapshot is taken
|
||||
MachineImageName string `json:"machineimage_name"`
|
||||
|
||||
// Name of the snapshot
|
||||
Name string `json:"name"`
|
||||
|
||||
// String indicating whether the parent volume is bootable or not
|
||||
ParentVolumeBootable string `json:"parent_volume_bootable"`
|
||||
|
||||
// Platform the snapshot is compatible with
|
||||
Platform string `json:"platform"`
|
||||
|
||||
// String determining whether the snapshot is remote or collocated
|
||||
Property string `json:"property"`
|
||||
|
||||
// The size of the snapshot in GB
|
||||
Size string `json:"size"`
|
||||
|
||||
// The ID of the snapshot. Generated by the server
|
||||
SnapshotID string `json:"snapshot_id"`
|
||||
|
||||
// The timestamp of the storage snapshot
|
||||
SnapshotTimestamp string `json:"snapshot_timestamp"`
|
||||
|
||||
// Timestamp for when the operation started
|
||||
StartTimestamp string `json:"start_timestamp"`
|
||||
|
||||
// Status of the snapshot
|
||||
Status string `json:"status"`
|
||||
|
||||
// Status Detail of the storage snapshot
|
||||
StatusDetail string `json:"status_detail"`
|
||||
|
||||
// Indicates the time that the current view of the storage volume snapshot was generated.
|
||||
StatusTimestamp string `json:"status_timestamp"`
|
||||
|
||||
// Array of tags for the snapshot
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri"`
|
||||
|
||||
// Name of the parent storage volume for the snapshot
|
||||
Volume string `json:"volume"`
|
||||
}
|
||||
|
||||
// CreateStorageVolumeSnapshotInput represents the body of an API request to create a new storage volume snapshot
|
||||
type CreateStorageVolumeSnapshotInput struct {
|
||||
// Description of the snapshot
|
||||
// Optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Name of the snapshot
|
||||
// Optional, will be generated if not specified
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Whether or not the parent volume is bootable
|
||||
// Optional
|
||||
ParentVolumeBootable string `json:"parent_volume_bootable,omitempty"`
|
||||
|
||||
// Whether collocated or remote
|
||||
// Optional, will be remote if unspecified
|
||||
Property string `json:"property,omitempty"`
|
||||
|
||||
// Array of tags for the snapshot
|
||||
// Optional
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Name of the volume to create the snapshot from
|
||||
// Required
|
||||
Volume string `json:"volume"`
|
||||
|
||||
// Timeout to wait for snapshot to be completed. Will use default if unspecified
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// CreateStorageVolumeSnapshot creates a snapshot based on the supplied information struct
|
||||
func (c *StorageVolumeSnapshotClient) CreateStorageVolumeSnapshot(input *CreateStorageVolumeSnapshotInput) (*StorageVolumeSnapshotInfo, error) {
|
||||
if input.Name != "" {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
}
|
||||
input.Volume = c.getQualifiedName(input.Volume)
|
||||
|
||||
var storageSnapshotInfo StorageVolumeSnapshotInfo
|
||||
if err := c.createResource(&input, &storageSnapshotInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForSnapshotCreateTimeout
|
||||
}
|
||||
|
||||
// The name of the snapshot could have been generated. Use the response name as input
|
||||
return c.waitForStorageSnapshotAvailable(storageSnapshotInfo.Name, input.Timeout)
|
||||
}
|
||||
|
||||
// GetStorageVolumeSnapshotInput represents the body of an API request to get information on a storage volume snapshot
|
||||
type GetStorageVolumeSnapshotInput struct {
|
||||
// Name of the snapshot
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// GetStorageVolumeSnapshot makes an API request to populate information on a storage volume snapshot
|
||||
func (c *StorageVolumeSnapshotClient) GetStorageVolumeSnapshot(input *GetStorageVolumeSnapshotInput) (*StorageVolumeSnapshotInfo, error) {
|
||||
var storageSnapshot StorageVolumeSnapshotInfo
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
if err := c.getResource(input.Name, &storageSnapshot); err != nil {
|
||||
if client.WasNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
return c.success(&storageSnapshot)
|
||||
}
|
||||
|
||||
// DeleteStorageVolumeSnapshotInput represents the body of an API request to delete a storage volume snapshot
|
||||
type DeleteStorageVolumeSnapshotInput struct {
|
||||
// Name of the snapshot to delete
|
||||
Name string `json:"name"`
|
||||
|
||||
// Timeout to wait for deletion, will use default if unspecified
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// DeleteStoragevolumeSnapshot makes an API request to delete a storage volume snapshot
|
||||
func (c *StorageVolumeSnapshotClient) DeleteStorageVolumeSnapshot(input *DeleteStorageVolumeSnapshotInput) error {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
|
||||
if err := c.deleteResource(input.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForSnapshotDeleteTimeout
|
||||
}
|
||||
|
||||
return c.waitForStorageSnapshotDeleted(input.Name, input.Timeout)
|
||||
}
|
||||
|
||||
func (c *StorageVolumeSnapshotClient) success(result *StorageVolumeSnapshotInfo) (*StorageVolumeSnapshotInfo, error) {
|
||||
c.unqualify(&result.Name)
|
||||
c.unqualify(&result.Volume)
|
||||
|
||||
sizeInGigaBytes, err := sizeInGigaBytes(result.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Size = sizeInGigaBytes
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Waits for a storage snapshot to become available
|
||||
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotAvailable(name string, timeout time.Duration) (*StorageVolumeSnapshotInfo, error) {
|
||||
var result *StorageVolumeSnapshotInfo
|
||||
|
||||
err := c.client.WaitFor(
|
||||
fmt.Sprintf("storage volume snapshot %s to become available", c.getQualifiedName(name)),
|
||||
timeout,
|
||||
func() (bool, error) {
|
||||
req := &GetStorageVolumeSnapshotInput{
|
||||
Name: name,
|
||||
}
|
||||
res, err := c.GetStorageVolumeSnapshot(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if res != nil {
|
||||
result = res
|
||||
if strings.ToLower(result.Status) == "completed" {
|
||||
return true, nil
|
||||
} else if strings.ToLower(result.Status) == "error" {
|
||||
return false, fmt.Errorf("Snapshot '%s' failed to create successfully. Status: %s Status Detail: %s", result.Name, result.Status, result.StatusDetail)
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Waits for a storage snapshot to be deleted
|
||||
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotDeleted(name string, timeout time.Duration) error {
|
||||
return c.client.WaitFor(
|
||||
fmt.Sprintf("storage volume snapshot %s to be deleted", c.getQualifiedName(name)),
|
||||
timeout,
|
||||
func() (bool, error) {
|
||||
req := &GetStorageVolumeSnapshotInput{
|
||||
Name: name,
|
||||
}
|
||||
res, err := c.GetStorageVolumeSnapshot(req)
|
||||
if res == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res == nil, nil
|
||||
})
|
||||
}
|
389
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go
generated
vendored
Normal file
389
vendor/github.com/hashicorp/go-oracle-terraform/compute/storage_volumes.go
generated
vendored
Normal file
|
@ -0,0 +1,389 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/client"
|
||||
)
|
||||
|
||||
const WaitForVolumeReadyTimeout = time.Duration(600 * time.Second)
|
||||
const WaitForVolumeDeleteTimeout = time.Duration(600 * time.Second)
|
||||
|
||||
// StorageVolumeClient is a client for the Storage Volume functions of the Compute API.
|
||||
type StorageVolumeClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
// StorageVolumes obtains a StorageVolumeClient which can be used to access to the
|
||||
// Storage Volume functions of the Compute API
|
||||
func (c *ComputeClient) StorageVolumes() *StorageVolumeClient {
|
||||
return &StorageVolumeClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "storage volume",
|
||||
ContainerPath: "/storage/volume/",
|
||||
ResourceRootPath: "/storage/volume",
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
type StorageVolumeKind string
|
||||
|
||||
const (
|
||||
StorageVolumeKindDefault StorageVolumeKind = "/oracle/public/storage/default"
|
||||
StorageVolumeKindLatency StorageVolumeKind = "/oracle/public/storage/latency"
|
||||
StorageVolumeKindSSD StorageVolumeKind = "/oracle/public/storage/ssd/gpl"
|
||||
)
|
||||
|
||||
// StorageVolumeInfo represents information retrieved from the service about a Storage Volume.
|
||||
type StorageVolumeInfo struct {
|
||||
// Shows the default account for your identity domain.
|
||||
Account string `json:"account,omitempty"`
|
||||
|
||||
// true indicates that the storage volume can also be used as a boot disk for an instance.
|
||||
// If you set the value to true, then you must specify values for the `ImageList` and `ImageListEntry` fields.
|
||||
Bootable bool `json:"bootable,omitempty"`
|
||||
|
||||
// The description of the storage volume.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// The hypervisor that this volume is compatible with.
|
||||
Hypervisor string `json:"hypervisor,omitempty"`
|
||||
|
||||
// Name of machine image to extract onto this volume when created. This information is provided only for bootable storage volumes.
|
||||
ImageList string `json:"imagelist,omitempty"`
|
||||
|
||||
// Specific imagelist entry version to extract.
|
||||
ImageListEntry int `json:"imagelist_entry,omitempty"`
|
||||
|
||||
// Three-part name of the machine image. This information is available if the volume is a bootable storage volume.
|
||||
MachineImage string `json:"machineimage_name,omitempty"`
|
||||
|
||||
// All volumes are managed volumes. Default value is true.
|
||||
Managed bool `json:"managed,omitempty"`
|
||||
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
|
||||
// The OS platform this volume is compatible with.
|
||||
Platform string `json:"platform,omitempty"`
|
||||
|
||||
// The storage-pool property: /oracle/public/storage/latency or /oracle/public/storage/default.
|
||||
Properties []string `json:"properties,omitempty"`
|
||||
|
||||
// Boolean field indicating whether this volume can be attached as readonly. If set to False the volume will be attached as read-write.
|
||||
ReadOnly bool `json:"readonly,omitempty"`
|
||||
|
||||
// The size of this storage volume in GB.
|
||||
Size string `json:"size"`
|
||||
|
||||
// Name of the parent snapshot from which the storage volume is restored or cloned.
|
||||
Snapshot string `json:"snapshot,omitempty"`
|
||||
|
||||
// Account of the parent snapshot from which the storage volume is restored.
|
||||
SnapshotAccount string `json:"snapshot_account,omitempty"`
|
||||
|
||||
// Id of the parent snapshot from which the storage volume is restored or cloned.
|
||||
SnapshotID string `json:"snapshot_id,omitempty"`
|
||||
|
||||
// TODO: this should become a Constant, if/when we have the values
|
||||
// The current state of the storage volume.
|
||||
Status string `json:"status,omitempty"`
|
||||
|
||||
// Details about the latest state of the storage volume.
|
||||
StatusDetail string `json:"status_detail,omitempty"`
|
||||
|
||||
// It indicates the time that the current view of the storage volume was generated.
|
||||
StatusTimestamp string `json:"status_timestamp,omitempty"`
|
||||
|
||||
// The storage pool from which this volume is allocated.
|
||||
StoragePool string `json:"storage_pool,omitempty"`
|
||||
|
||||
// Comma-separated strings that tag the storage volume.
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Uniform Resource Identifier
|
||||
URI string `json:"uri,omitempty"`
|
||||
}
|
||||
|
||||
func (c *StorageVolumeClient) getStorageVolumePath(name string) string {
|
||||
return c.getObjectPath("/storage/volume", name)
|
||||
}
|
||||
|
||||
// CreateStorageVolumeInput represents the body of an API request to create a new Storage Volume.
|
||||
type CreateStorageVolumeInput struct {
|
||||
// true indicates that the storage volume can also be used as a boot disk for an instance.
|
||||
// If you set the value to true, then you must specify values for the `ImageList` and `ImageListEntry` fields.
|
||||
Bootable bool `json:"bootable,omitempty"`
|
||||
|
||||
// The description of the storage volume.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Name of machine image to extract onto this volume when created. This information is provided only for bootable storage volumes.
|
||||
ImageList string `json:"imagelist,omitempty"`
|
||||
|
||||
// Specific imagelist entry version to extract.
|
||||
ImageListEntry int `json:"imagelist_entry,omitempty"`
|
||||
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
|
||||
// The storage-pool property: /oracle/public/storage/latency or /oracle/public/storage/default.
|
||||
Properties []string `json:"properties,omitempty"`
|
||||
|
||||
// The size of this storage volume in GB.
|
||||
Size string `json:"size"`
|
||||
|
||||
// Name of the parent snapshot from which the storage volume is restored or cloned.
|
||||
Snapshot string `json:"snapshot,omitempty"`
|
||||
|
||||
// Account of the parent snapshot from which the storage volume is restored.
|
||||
SnapshotAccount string `json:"snapshot_account,omitempty"`
|
||||
|
||||
// Id of the parent snapshot from which the storage volume is restored or cloned.
|
||||
SnapshotID string `json:"snapshot_id,omitempty"`
|
||||
|
||||
// Comma-separated strings that tag the storage volume.
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Timeout to wait for storage volume creation.
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// CreateStorageVolume uses the given CreateStorageVolumeInput to create a new Storage Volume.
|
||||
func (c *StorageVolumeClient) CreateStorageVolume(input *CreateStorageVolumeInput) (*StorageVolumeInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
input.ImageList = c.getQualifiedName(input.ImageList)
|
||||
|
||||
sizeInBytes, err := sizeInBytes(input.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.Size = sizeInBytes
|
||||
|
||||
var storageInfo StorageVolumeInfo
|
||||
if err := c.createResource(&input, &storageInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Should never be nil, as we set this in the provider; but protect against it anyways.
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForVolumeReadyTimeout
|
||||
}
|
||||
|
||||
volume, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.Timeout)
|
||||
if err != nil {
|
||||
if volume != nil {
|
||||
deleteInput := &DeleteStorageVolumeInput{
|
||||
Name: volume.Name,
|
||||
}
|
||||
|
||||
if err := c.DeleteStorageVolume(deleteInput); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return volume, err
|
||||
}
|
||||
|
||||
// DeleteStorageVolumeInput represents the body of an API request to delete a Storage Volume.
|
||||
type DeleteStorageVolumeInput struct {
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
|
||||
// Timeout to wait for storage volume deletion
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// DeleteStorageVolume deletes the specified storage volume.
|
||||
func (c *StorageVolumeClient) DeleteStorageVolume(input *DeleteStorageVolumeInput) error {
|
||||
if err := c.deleteResource(input.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Should never be nil, but protect against it anyways
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForVolumeDeleteTimeout
|
||||
}
|
||||
|
||||
return c.waitForStorageVolumeToBeDeleted(input.Name, input.Timeout)
|
||||
}
|
||||
|
||||
// GetStorageVolumeInput represents the body of an API request to obtain a Storage Volume.
|
||||
type GetStorageVolumeInput struct {
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *StorageVolumeClient) success(result *StorageVolumeInfo) (*StorageVolumeInfo, error) {
|
||||
c.unqualify(&result.ImageList)
|
||||
c.unqualify(&result.Name)
|
||||
c.unqualify(&result.Snapshot)
|
||||
|
||||
sizeInMegaBytes, err := sizeInGigaBytes(result.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Size = sizeInMegaBytes
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetStorageVolume gets Storage Volume information for the specified storage volume.
|
||||
func (c *StorageVolumeClient) GetStorageVolume(input *GetStorageVolumeInput) (*StorageVolumeInfo, error) {
|
||||
var storageVolume StorageVolumeInfo
|
||||
if err := c.getResource(input.Name, &storageVolume); err != nil {
|
||||
if client.WasNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&storageVolume)
|
||||
}
|
||||
|
||||
// UpdateStorageVolumeInput represents the body of an API request to update a Storage Volume.
|
||||
type UpdateStorageVolumeInput struct {
|
||||
// The description of the storage volume.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Name of machine image to extract onto this volume when created. This information is provided only for bootable storage volumes.
|
||||
ImageList string `json:"imagelist,omitempty"`
|
||||
|
||||
// Specific imagelist entry version to extract.
|
||||
ImageListEntry int `json:"imagelist_entry,omitempty"`
|
||||
|
||||
// The three-part name of the object (/Compute-identity_domain/user/object).
|
||||
Name string `json:"name"`
|
||||
|
||||
// The storage-pool property: /oracle/public/storage/latency or /oracle/public/storage/default.
|
||||
Properties []string `json:"properties,omitempty"`
|
||||
|
||||
// The size of this storage volume in GB.
|
||||
Size string `json:"size"`
|
||||
|
||||
// Name of the parent snapshot from which the storage volume is restored or cloned.
|
||||
Snapshot string `json:"snapshot,omitempty"`
|
||||
|
||||
// Account of the parent snapshot from which the storage volume is restored.
|
||||
SnapshotAccount string `json:"snapshot_account,omitempty"`
|
||||
|
||||
// Id of the parent snapshot from which the storage volume is restored or cloned.
|
||||
SnapshotID string `json:"snapshot_id,omitempty"`
|
||||
|
||||
// Comma-separated strings that tag the storage volume.
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Time to wait for storage volume ready
|
||||
Timeout time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
// UpdateStorageVolume updates the specified storage volume, optionally modifying size, description and tags.
|
||||
func (c *StorageVolumeClient) UpdateStorageVolume(input *UpdateStorageVolumeInput) (*StorageVolumeInfo, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
input.ImageList = c.getQualifiedName(input.ImageList)
|
||||
|
||||
sizeInBytes, err := sizeInBytes(input.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.Size = sizeInBytes
|
||||
|
||||
path := c.getStorageVolumePath(input.Name)
|
||||
_, err = c.executeRequest("PUT", path, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if input.Timeout == 0 {
|
||||
input.Timeout = WaitForVolumeReadyTimeout
|
||||
}
|
||||
|
||||
volumeInfo, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.Timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return volumeInfo, nil
|
||||
}
|
||||
|
||||
// waitForStorageVolumeToBecomeAvailable waits until a new Storage Volume is available (i.e. has finished initialising or updating).
|
||||
func (c *StorageVolumeClient) waitForStorageVolumeToBecomeAvailable(name string, timeout time.Duration) (*StorageVolumeInfo, error) {
|
||||
var waitResult *StorageVolumeInfo
|
||||
|
||||
err := c.client.WaitFor(
|
||||
fmt.Sprintf("storage volume %s to become available", c.getQualifiedName(name)),
|
||||
timeout,
|
||||
func() (bool, error) {
|
||||
getRequest := &GetStorageVolumeInput{
|
||||
Name: name,
|
||||
}
|
||||
result, err := c.GetStorageVolume(getRequest)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if result != nil {
|
||||
waitResult = result
|
||||
if strings.ToLower(waitResult.Status) == "online" {
|
||||
return true, nil
|
||||
}
|
||||
if strings.ToLower(waitResult.Status) == "error" {
|
||||
return false, fmt.Errorf("Error Creating Storage Volume: %s", waitResult.StatusDetail)
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
|
||||
return waitResult, err
|
||||
}
|
||||
|
||||
// waitForStorageVolumeToBeDeleted waits until the specified storage volume has been deleted.
|
||||
func (c *StorageVolumeClient) waitForStorageVolumeToBeDeleted(name string, timeout time.Duration) error {
|
||||
return c.client.WaitFor(
|
||||
fmt.Sprintf("storage volume %s to be deleted", c.getQualifiedName(name)),
|
||||
timeout,
|
||||
func() (bool, error) {
|
||||
getRequest := &GetStorageVolumeInput{
|
||||
Name: name,
|
||||
}
|
||||
result, err := c.GetStorageVolume(getRequest)
|
||||
if result == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result == nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func sizeInGigaBytes(input string) (string, error) {
|
||||
sizeInBytes, err := strconv.Atoi(input)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sizeInKB := sizeInBytes / 1024
|
||||
sizeInMB := sizeInKB / 1024
|
||||
sizeInGb := sizeInMB / 1024
|
||||
return strconv.Itoa(sizeInGb), nil
|
||||
}
|
||||
|
||||
func sizeInBytes(input string) (string, error) {
|
||||
sizeInGB, err := strconv.Atoi(input)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sizeInMB := sizeInGB * 1024
|
||||
sizeInKB := sizeInMB * 1024
|
||||
sizeInBytes := sizeInKB * 1024
|
||||
return strconv.Itoa(sizeInBytes), nil
|
||||
}
|
119
vendor/github.com/hashicorp/go-oracle-terraform/compute/test_utils.go
generated
vendored
Normal file
119
vendor/github.com/hashicorp/go-oracle-terraform/compute/test_utils.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
package compute
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-oracle-terraform/opc"
|
||||
)
|
||||
|
||||
const (
|
||||
_ClientTestUser = "test-user"
|
||||
_ClientTestDomain = "test-domain"
|
||||
)
|
||||
|
||||
func newAuthenticatingServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if os.Getenv("ORACLE_LOG") != "" {
|
||||
log.Printf("[DEBUG] Received request: %s, %s\n", r.Method, r.URL)
|
||||
}
|
||||
|
||||
if r.URL.Path == "/authenticate/" {
|
||||
http.SetCookie(w, &http.Cookie{Name: "testAuthCookie", Value: "cookie value"})
|
||||
// w.WriteHeader(200)
|
||||
} else {
|
||||
handler(w, r)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func getTestClient(c *opc.Config) (*ComputeClient, error) {
|
||||
// Build up config with default values if omitted
|
||||
if c.APIEndpoint == nil {
|
||||
if os.Getenv("OPC_ENDPOINT") == "" {
|
||||
panic("OPC_ENDPOINT not set in environment")
|
||||
}
|
||||
endpoint, err := url.Parse(os.Getenv("OPC_ENDPOINT"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.APIEndpoint = endpoint
|
||||
}
|
||||
|
||||
if c.IdentityDomain == nil {
|
||||
domain := os.Getenv("OPC_IDENTITY_DOMAIN")
|
||||
c.IdentityDomain = &domain
|
||||
}
|
||||
|
||||
if c.Username == nil {
|
||||
username := os.Getenv("OPC_USERNAME")
|
||||
c.Username = &username
|
||||
}
|
||||
|
||||
if c.Password == nil {
|
||||
password := os.Getenv("OPC_PASSWORD")
|
||||
c.Password = &password
|
||||
}
|
||||
|
||||
if c.HTTPClient == nil {
|
||||
c.HTTPClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSHandshakeTimeout: 120 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
return NewComputeClient(c)
|
||||
}
|
||||
|
||||
func getBlankTestClient() (*ComputeClient, *httptest.Server, error) {
|
||||
server := newAuthenticatingServer(func(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
|
||||
endpoint, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
server.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
client, err := getTestClient(&opc.Config{
|
||||
IdentityDomain: opc.String(_ClientTestDomain),
|
||||
Username: opc.String(_ClientTestUser),
|
||||
APIEndpoint: endpoint,
|
||||
})
|
||||
if err != nil {
|
||||
server.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
return client, server, nil
|
||||
}
|
||||
|
||||
// Returns a stub client with default values, and a custom API Endpoint
|
||||
func getStubClient(endpoint *url.URL) (*ComputeClient, error) {
|
||||
domain := "test"
|
||||
username := "test"
|
||||
password := "test"
|
||||
config := &opc.Config{
|
||||
IdentityDomain: &domain,
|
||||
Username: &username,
|
||||
Password: &password,
|
||||
APIEndpoint: endpoint,
|
||||
}
|
||||
return getTestClient(config)
|
||||
}
|
||||
|
||||
func unmarshalRequestBody(t *testing.T, r *http.Request, target interface{}) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(r.Body)
|
||||
err := json.Unmarshal(buf.Bytes(), target)
|
||||
if err != nil {
|
||||
t.Fatalf("Error marshalling request: %s", err)
|
||||
}
|
||||
}
|
52
vendor/github.com/hashicorp/go-oracle-terraform/compute/virtual_nic.go
generated
vendored
Normal file
52
vendor/github.com/hashicorp/go-oracle-terraform/compute/virtual_nic.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
package compute
|
||||
|
||||
type VirtNICsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
func (c *ComputeClient) VirtNICs() *VirtNICsClient {
|
||||
return &VirtNICsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "Virtual NIC",
|
||||
ContainerPath: "/network/v1/vnic/",
|
||||
ResourceRootPath: "/network/v1/vnic",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type VirtualNIC struct {
|
||||
// Description of the object.
|
||||
Description string `json:"description"`
|
||||
// MAC address of this VNIC.
|
||||
MACAddress string `json:"macAddress"`
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the Virtual NIC.
|
||||
Name string `json:"name"`
|
||||
// Tags associated with the object.
|
||||
Tags []string `json:"tags"`
|
||||
// True if the VNIC is of type "transit".
|
||||
TransitFlag bool `json:"transitFlag"`
|
||||
// Uniform Resource Identifier
|
||||
Uri string `json:"uri"`
|
||||
}
|
||||
|
||||
// Can only GET a virtual NIC, not update, create, or delete
|
||||
type GetVirtualNICInput struct {
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the Virtual NIC.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *VirtNICsClient) GetVirtualNIC(input *GetVirtualNICInput) (*VirtualNIC, error) {
|
||||
var virtNIC VirtualNIC
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
if err := c.getResource(input.Name, &virtNIC); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.success(&virtNIC)
|
||||
}
|
||||
|
||||
func (c *VirtNICsClient) success(info *VirtualNIC) (*VirtualNIC, error) {
|
||||
c.unqualify(&info.Name)
|
||||
return info, nil
|
||||
}
|
154
vendor/github.com/hashicorp/go-oracle-terraform/compute/virtual_nic_sets.go
generated
vendored
Normal file
154
vendor/github.com/hashicorp/go-oracle-terraform/compute/virtual_nic_sets.go
generated
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
package compute
|
||||
|
||||
type VirtNICSetsClient struct {
|
||||
ResourceClient
|
||||
}
|
||||
|
||||
func (c *ComputeClient) VirtNICSets() *VirtNICSetsClient {
|
||||
return &VirtNICSetsClient{
|
||||
ResourceClient: ResourceClient{
|
||||
ComputeClient: c,
|
||||
ResourceDescription: "Virtual NIC Set",
|
||||
ContainerPath: "/network/v1/vnicset/",
|
||||
ResourceRootPath: "/network/v1/vnicset",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Describes an existing virtual nic set
|
||||
type VirtualNICSet struct {
|
||||
// List of ACLs applied to the VNICs in the set.
|
||||
AppliedACLs []string `json:"appliedAcls"`
|
||||
// Description of the VNIC Set.
|
||||
Description string `json:"description"`
|
||||
// Name of the VNIC set.
|
||||
Name string `json:"name"`
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the virtual NIC set.
|
||||
Tags []string `json:"tags"`
|
||||
// Uniform Resource Identifier
|
||||
Uri string `json:"uri"`
|
||||
// List of VNICs associated with this VNIC set.
|
||||
VirtualNICs []string `json:"vnics"`
|
||||
}
|
||||
|
||||
type CreateVirtualNICSetInput struct {
|
||||
// List of ACLs applied to the VNICs in the set.
|
||||
// Optional
|
||||
AppliedACLs []string `json:"appliedAcls"`
|
||||
// Description of the object.
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the virtual NIC set.
|
||||
// Object names can contain only alphanumeric, underscore (_), dash (-), and period (.) characters. Object names are case-sensitive.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
// Tags associated with this VNIC set.
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
// List of VNICs associated with this VNIC set.
|
||||
// Optional
|
||||
VirtualNICs []string `json:"vnics"`
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) CreateVirtualNICSet(input *CreateVirtualNICSetInput) (*VirtualNICSet, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
input.AppliedACLs = c.getQualifiedAcls(input.AppliedACLs)
|
||||
qualifiedNics := c.getQualifiedList(input.VirtualNICs)
|
||||
if len(qualifiedNics) != 0 {
|
||||
input.VirtualNICs = qualifiedNics
|
||||
}
|
||||
|
||||
var virtNicSet VirtualNICSet
|
||||
if err := c.createResource(input, &virtNicSet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&virtNicSet)
|
||||
}
|
||||
|
||||
type GetVirtualNICSetInput struct {
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the virtual NIC set.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) GetVirtualNICSet(input *GetVirtualNICSetInput) (*VirtualNICSet, error) {
|
||||
var virtNicSet VirtualNICSet
|
||||
// Qualify Name
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
if err := c.getResource(input.Name, &virtNicSet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&virtNicSet)
|
||||
}
|
||||
|
||||
type UpdateVirtualNICSetInput struct {
|
||||
// List of ACLs applied to the VNICs in the set.
|
||||
// Optional
|
||||
AppliedACLs []string `json:"appliedAcls"`
|
||||
// Description of the object.
|
||||
// Optional
|
||||
Description string `json:"description"`
|
||||
// The three-part name (/Compute-identity_domain/user/object) of the virtual NIC set.
|
||||
// Object names can contain only alphanumeric, underscore (_), dash (-), and period (.) characters. Object names are case-sensitive.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
// Tags associated with this VNIC set.
|
||||
// Optional
|
||||
Tags []string `json:"tags"`
|
||||
// List of VNICs associated with this VNIC set.
|
||||
// Optional
|
||||
VirtualNICs []string `json:"vnics"`
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) UpdateVirtualNICSet(input *UpdateVirtualNICSetInput) (*VirtualNICSet, error) {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
input.AppliedACLs = c.getQualifiedAcls(input.AppliedACLs)
|
||||
// Qualify VirtualNICs
|
||||
qualifiedVNICs := c.getQualifiedList(input.VirtualNICs)
|
||||
if len(qualifiedVNICs) != 0 {
|
||||
input.VirtualNICs = qualifiedVNICs
|
||||
}
|
||||
|
||||
var virtNICSet VirtualNICSet
|
||||
if err := c.updateResource(input.Name, input, &virtNICSet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.success(&virtNICSet)
|
||||
}
|
||||
|
||||
type DeleteVirtualNICSetInput struct {
|
||||
// The name of the virtual NIC set.
|
||||
// Required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) DeleteVirtualNICSet(input *DeleteVirtualNICSetInput) error {
|
||||
input.Name = c.getQualifiedName(input.Name)
|
||||
return c.deleteResource(input.Name)
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) getQualifiedAcls(acls []string) []string {
|
||||
qualifiedAcls := []string{}
|
||||
for _, acl := range acls {
|
||||
qualifiedAcls = append(qualifiedAcls, c.getQualifiedName(acl))
|
||||
}
|
||||
return qualifiedAcls
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) unqualifyAcls(acls []string) []string {
|
||||
unqualifiedAcls := []string{}
|
||||
for _, acl := range acls {
|
||||
unqualifiedAcls = append(unqualifiedAcls, c.getUnqualifiedName(acl))
|
||||
}
|
||||
return unqualifiedAcls
|
||||
}
|
||||
|
||||
func (c *VirtNICSetsClient) success(info *VirtualNICSet) (*VirtualNICSet, error) {
|
||||
c.unqualify(&info.Name)
|
||||
info.AppliedACLs = c.unqualifyAcls(info.AppliedACLs)
|
||||
info.VirtualNICs = c.getUnqualifiedList(info.VirtualNICs)
|
||||
return info, nil
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Username *string
|
||||
Password *string
|
||||
IdentityDomain *string
|
||||
APIEndpoint *url.URL
|
||||
MaxRetries *int
|
||||
LogLevel LogLevelType
|
||||
Logger Logger
|
||||
HTTPClient *http.Client
|
||||
UserAgent *string
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
return &Config{}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package opc
|
||||
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package opc
|
||||
|
||||
import "fmt"
|
||||
|
||||
type OracleError struct {
|
||||
StatusCode int
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e OracleError) Error() string {
|
||||
return fmt.Sprintf("%d: %s", e.StatusCode, e.Message)
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
LogOff LogLevelType = 0
|
||||
LogDebug LogLevelType = 1
|
||||
)
|
||||
|
||||
type LogLevelType uint
|
||||
|
||||
// Logger interface. Should be satisfied by Terraform's logger as well as the Default logger
|
||||
type Logger interface {
|
||||
Log(...interface{})
|
||||
}
|
||||
|
||||
type LoggerFunc func(...interface{})
|
||||
|
||||
func (f LoggerFunc) Log(args ...interface{}) {
|
||||
f(args...)
|
||||
}
|
||||
|
||||
// Returns a default logger if one isn't specified during configuration
|
||||
func NewDefaultLogger() Logger {
|
||||
logWriter, err := LogOutput()
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting up log writer: %s", err)
|
||||
}
|
||||
return &defaultLogger{
|
||||
logger: log.New(logWriter, "", log.LstdFlags),
|
||||
}
|
||||
}
|
||||
|
||||
// Default logger to satisfy the logger interface
|
||||
type defaultLogger struct {
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func (l defaultLogger) Log(args ...interface{}) {
|
||||
l.logger.Println(args...)
|
||||
}
|
||||
|
||||
func LogOutput() (logOutput io.Writer, err error) {
|
||||
// Default to nil
|
||||
logOutput = ioutil.Discard
|
||||
|
||||
logLevel := LogLevel()
|
||||
if logLevel == LogOff {
|
||||
return
|
||||
}
|
||||
|
||||
// Logging is on, set output to STDERR
|
||||
logOutput = os.Stderr
|
||||
return
|
||||
}
|
||||
|
||||
// Gets current Log Level from the ORACLE_LOG env var
|
||||
func LogLevel() LogLevelType {
|
||||
envLevel := os.Getenv("ORACLE_LOG")
|
||||
if envLevel == "" {
|
||||
return LogOff
|
||||
} else {
|
||||
return LogDebug
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# mapstructure
|
||||
# mapstructure [![Godoc](https://godoc.org/github.com/mitchell/mapstructure?status.svg)](https://godoc.org/github.com/mitchell/mapstructure)
|
||||
|
||||
mapstructure is a Go library for decoding generic map values to structures
|
||||
and vice versa, while providing helpful error handling.
|
||||
|
|
|
@ -38,12 +38,6 @@ func DecodeHookExec(
|
|||
raw DecodeHookFunc,
|
||||
from reflect.Type, to reflect.Type,
|
||||
data interface{}) (interface{}, error) {
|
||||
// Build our arguments that reflect expects
|
||||
argVals := make([]reflect.Value, 3)
|
||||
argVals[0] = reflect.ValueOf(from)
|
||||
argVals[1] = reflect.ValueOf(to)
|
||||
argVals[2] = reflect.ValueOf(data)
|
||||
|
||||
switch f := typedDecodeHook(raw).(type) {
|
||||
case DecodeHookFuncType:
|
||||
return f(from, to, data)
|
||||
|
@ -72,7 +66,10 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
|||
}
|
||||
|
||||
// Modify the from kind to be correct with the new data
|
||||
f = reflect.ValueOf(data).Type()
|
||||
f = nil
|
||||
if val := reflect.ValueOf(data); val.IsValid() {
|
||||
f = val.Type()
|
||||
}
|
||||
}
|
||||
|
||||
return data, nil
|
||||
|
@ -118,6 +115,11 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
|
||||
// the decoder.
|
||||
//
|
||||
// Note that this is significantly different from the WeaklyTypedInput option
|
||||
// of the DecoderConfig.
|
||||
func WeaklyTypedHook(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
|
@ -129,9 +131,8 @@ func WeaklyTypedHook(
|
|||
case reflect.Bool:
|
||||
if dataVal.Bool() {
|
||||
return "1", nil
|
||||
} else {
|
||||
return "0", nil
|
||||
}
|
||||
return "0", nil
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
|
||||
case reflect.Int:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// The mapstructure package exposes functionality to convert an
|
||||
// abitrary map[string]interface{} into a native Go structure.
|
||||
// Package mapstructure exposes functionality to convert an arbitrary
|
||||
// map[string]interface{} into a native Go structure.
|
||||
//
|
||||
// The Go structure can be arbitrarily complex, containing slices,
|
||||
// other structs, etc. and the decoder will properly decode nested
|
||||
|
@ -8,6 +8,7 @@
|
|||
package mapstructure
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
@ -31,7 +32,12 @@ import (
|
|||
// both.
|
||||
type DecodeHookFunc interface{}
|
||||
|
||||
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
|
||||
// the source and target types.
|
||||
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
|
||||
|
||||
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
|
||||
// source and target types.
|
||||
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
|
||||
|
||||
// DecoderConfig is the configuration that is used to create a new decoder
|
||||
|
@ -67,6 +73,10 @@ type DecoderConfig struct {
|
|||
// FALSE, false, False. Anything else is an error)
|
||||
// - empty array = empty map and vice versa
|
||||
// - negative numbers to overflowed uint values (base 10)
|
||||
// - slice of maps to a merged map
|
||||
// - single values are converted to slices if required. Each
|
||||
// element is weakly decoded. For example: "4" can become []int{4}
|
||||
// if the target type is an int slice.
|
||||
//
|
||||
WeaklyTypedInput bool
|
||||
|
||||
|
@ -200,7 +210,7 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
|
|||
d.config.DecodeHook,
|
||||
dataVal.Type(), val.Type(), data)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error decoding '%s': %s", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,6 +237,10 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
|
|||
err = d.decodePtr(name, data, val)
|
||||
case reflect.Slice:
|
||||
err = d.decodeSlice(name, data, val)
|
||||
case reflect.Array:
|
||||
err = d.decodeArray(name, data, val)
|
||||
case reflect.Func:
|
||||
err = d.decodeFunc(name, data, val)
|
||||
default:
|
||||
// If we reached this point then we weren't able to decode it
|
||||
return fmt.Errorf("%s: unsupported type: %s", name, dataKind)
|
||||
|
@ -245,6 +259,10 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
|
|||
// value to "data" of that type.
|
||||
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.ValueOf(data)
|
||||
if !dataVal.IsValid() {
|
||||
dataVal = reflect.Zero(val.Type())
|
||||
}
|
||||
|
||||
dataValType := dataVal.Type()
|
||||
if !dataValType.AssignableTo(val.Type()) {
|
||||
return fmt.Errorf(
|
||||
|
@ -276,12 +294,22 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
|
|||
val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
|
||||
case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
|
||||
val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
|
||||
case dataKind == reflect.Slice && d.config.WeaklyTypedInput:
|
||||
case dataKind == reflect.Slice && d.config.WeaklyTypedInput,
|
||||
dataKind == reflect.Array && d.config.WeaklyTypedInput:
|
||||
dataType := dataVal.Type()
|
||||
elemKind := dataType.Elem().Kind()
|
||||
switch {
|
||||
case elemKind == reflect.Uint8:
|
||||
val.SetString(string(dataVal.Interface().([]uint8)))
|
||||
switch elemKind {
|
||||
case reflect.Uint8:
|
||||
var uints []uint8
|
||||
if dataKind == reflect.Array {
|
||||
uints = make([]uint8, dataVal.Len(), dataVal.Len())
|
||||
for i := range uints {
|
||||
uints[i] = dataVal.Index(i).Interface().(uint8)
|
||||
}
|
||||
} else {
|
||||
uints = dataVal.Interface().([]uint8)
|
||||
}
|
||||
val.SetString(string(uints))
|
||||
default:
|
||||
converted = false
|
||||
}
|
||||
|
@ -301,6 +329,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
|
|||
func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.ValueOf(data)
|
||||
dataKind := getKind(dataVal)
|
||||
dataType := dataVal.Type()
|
||||
|
||||
switch {
|
||||
case dataKind == reflect.Int:
|
||||
|
@ -322,6 +351,14 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
|
|||
} else {
|
||||
return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
|
||||
}
|
||||
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
||||
jn := data.(json.Number)
|
||||
i, err := jn.Int64()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"error decoding json.Number into %s: %s", name, err)
|
||||
}
|
||||
val.SetInt(i)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||
|
@ -408,6 +445,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
|
|||
func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.ValueOf(data)
|
||||
dataKind := getKind(dataVal)
|
||||
dataType := dataVal.Type()
|
||||
|
||||
switch {
|
||||
case dataKind == reflect.Int:
|
||||
|
@ -415,7 +453,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
|
|||
case dataKind == reflect.Uint:
|
||||
val.SetFloat(float64(dataVal.Uint()))
|
||||
case dataKind == reflect.Float32:
|
||||
val.SetFloat(float64(dataVal.Float()))
|
||||
val.SetFloat(dataVal.Float())
|
||||
case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
|
||||
if dataVal.Bool() {
|
||||
val.SetFloat(1)
|
||||
|
@ -429,6 +467,14 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
|
|||
} else {
|
||||
return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
|
||||
}
|
||||
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
|
||||
jn := data.(json.Number)
|
||||
i, err := jn.Float64()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"error decoding json.Number into %s: %s", name, err)
|
||||
}
|
||||
val.SetFloat(i)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||
|
@ -456,15 +502,30 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
|
|||
// Check input type
|
||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||
if dataVal.Kind() != reflect.Map {
|
||||
// Accept empty array/slice instead of an empty map in weakly typed mode
|
||||
if d.config.WeaklyTypedInput &&
|
||||
(dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) &&
|
||||
dataVal.Len() == 0 {
|
||||
val.Set(valMap)
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
|
||||
// In weak mode, we accept a slice of maps as an input...
|
||||
if d.config.WeaklyTypedInput {
|
||||
switch dataVal.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
// Special case for BC reasons (covered by tests)
|
||||
if dataVal.Len() == 0 {
|
||||
val.Set(valMap)
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < dataVal.Len(); i++ {
|
||||
err := d.decode(
|
||||
fmt.Sprintf("%s[%d]", name, i),
|
||||
dataVal.Index(i).Interface(), val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
|
||||
}
|
||||
|
||||
// Accumulate errors
|
||||
|
@ -507,7 +568,12 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
|
|||
// into that. Then set the value of the pointer to this type.
|
||||
valType := val.Type()
|
||||
valElemType := valType.Elem()
|
||||
realVal := reflect.New(valElemType)
|
||||
|
||||
realVal := val
|
||||
if realVal.IsNil() || d.config.ZeroFields {
|
||||
realVal = reflect.New(valElemType)
|
||||
}
|
||||
|
||||
if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -516,6 +582,19 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
|
||||
// Create an element of the concrete (non pointer) type and decode
|
||||
// into that. Then set the value of the pointer to this type.
|
||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||
if val.Type() != dataVal.Type() {
|
||||
return fmt.Errorf(
|
||||
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||
name, val.Type(), dataVal.Type())
|
||||
}
|
||||
val.Set(dataVal)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||
dataValKind := dataVal.Kind()
|
||||
|
@ -523,26 +602,44 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
|||
valElemType := valType.Elem()
|
||||
sliceType := reflect.SliceOf(valElemType)
|
||||
|
||||
// Check input type
|
||||
if dataValKind != reflect.Array && dataValKind != reflect.Slice {
|
||||
// Accept empty map instead of array/slice in weakly typed mode
|
||||
if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 {
|
||||
val.Set(reflect.MakeSlice(sliceType, 0, 0))
|
||||
return nil
|
||||
} else {
|
||||
valSlice := val
|
||||
if valSlice.IsNil() || d.config.ZeroFields {
|
||||
// Check input type
|
||||
if dataValKind != reflect.Array && dataValKind != reflect.Slice {
|
||||
if d.config.WeaklyTypedInput {
|
||||
switch {
|
||||
// Empty maps turn into empty slices
|
||||
case dataValKind == reflect.Map:
|
||||
if dataVal.Len() == 0 {
|
||||
val.Set(reflect.MakeSlice(sliceType, 0, 0))
|
||||
return nil
|
||||
}
|
||||
|
||||
// All other types we try to convert to the slice type
|
||||
// and "lift" it into it. i.e. a string becomes a string slice.
|
||||
default:
|
||||
// Just re-try this function with data as a slice.
|
||||
return d.decodeSlice(name, []interface{}{data}, val)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf(
|
||||
"'%s': source data must be an array or slice, got %s", name, dataValKind)
|
||||
}
|
||||
}
|
||||
|
||||
// Make a new slice to hold our result, same size as the original data.
|
||||
valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
|
||||
}
|
||||
|
||||
// Make a new slice to hold our result, same size as the original data.
|
||||
valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
|
||||
}
|
||||
|
||||
// Accumulate any errors
|
||||
errors := make([]string, 0)
|
||||
|
||||
for i := 0; i < dataVal.Len(); i++ {
|
||||
currentData := dataVal.Index(i).Interface()
|
||||
for valSlice.Len() <= i {
|
||||
valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
|
||||
}
|
||||
currentField := valSlice.Index(i)
|
||||
|
||||
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
||||
|
@ -562,6 +659,73 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||
dataValKind := dataVal.Kind()
|
||||
valType := val.Type()
|
||||
valElemType := valType.Elem()
|
||||
arrayType := reflect.ArrayOf(valType.Len(), valElemType)
|
||||
|
||||
valArray := val
|
||||
|
||||
if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields {
|
||||
// Check input type
|
||||
if dataValKind != reflect.Array && dataValKind != reflect.Slice {
|
||||
if d.config.WeaklyTypedInput {
|
||||
switch {
|
||||
// Empty maps turn into empty arrays
|
||||
case dataValKind == reflect.Map:
|
||||
if dataVal.Len() == 0 {
|
||||
val.Set(reflect.Zero(arrayType))
|
||||
return nil
|
||||
}
|
||||
|
||||
// All other types we try to convert to the array type
|
||||
// and "lift" it into it. i.e. a string becomes a string array.
|
||||
default:
|
||||
// Just re-try this function with data as a slice.
|
||||
return d.decodeArray(name, []interface{}{data}, val)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf(
|
||||
"'%s': source data must be an array or slice, got %s", name, dataValKind)
|
||||
|
||||
}
|
||||
if dataVal.Len() > arrayType.Len() {
|
||||
return fmt.Errorf(
|
||||
"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
|
||||
|
||||
}
|
||||
|
||||
// Make a new array to hold our result, same size as the original data.
|
||||
valArray = reflect.New(arrayType).Elem()
|
||||
}
|
||||
|
||||
// Accumulate any errors
|
||||
errors := make([]string, 0)
|
||||
|
||||
for i := 0; i < dataVal.Len(); i++ {
|
||||
currentData := dataVal.Index(i).Interface()
|
||||
currentField := valArray.Index(i)
|
||||
|
||||
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
||||
if err := d.decode(fieldName, currentData, currentField); err != nil {
|
||||
errors = appendErrors(errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, set the value to the array we built up
|
||||
val.Set(valArray)
|
||||
|
||||
// If there were errors, we return those
|
||||
if len(errors) > 0 {
|
||||
return &Error{errors}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
|
||||
dataVal := reflect.Indirect(reflect.ValueOf(data))
|
||||
|
||||
|
@ -601,23 +765,20 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
|
||||
// Compile the list of all the fields that we're going to be decoding
|
||||
// from all the structs.
|
||||
fields := make(map[*reflect.StructField]reflect.Value)
|
||||
type field struct {
|
||||
field reflect.StructField
|
||||
val reflect.Value
|
||||
}
|
||||
fields := []field{}
|
||||
for len(structs) > 0 {
|
||||
structVal := structs[0]
|
||||
structs = structs[1:]
|
||||
|
||||
structType := structVal.Type()
|
||||
|
||||
for i := 0; i < structType.NumField(); i++ {
|
||||
fieldType := structType.Field(i)
|
||||
|
||||
if fieldType.Anonymous {
|
||||
fieldKind := fieldType.Type.Kind()
|
||||
if fieldKind != reflect.Struct {
|
||||
errors = appendErrors(errors,
|
||||
fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind))
|
||||
continue
|
||||
}
|
||||
}
|
||||
fieldKind := fieldType.Type.Kind()
|
||||
|
||||
// If "squash" is specified in the tag, we squash the field down.
|
||||
squash := false
|
||||
|
@ -630,19 +791,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
}
|
||||
|
||||
if squash {
|
||||
structs = append(structs, val.FieldByName(fieldType.Name))
|
||||
if fieldKind != reflect.Struct {
|
||||
errors = appendErrors(errors,
|
||||
fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind))
|
||||
} else {
|
||||
structs = append(structs, structVal.FieldByName(fieldType.Name))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Normal struct field, store it away
|
||||
fields[&fieldType] = structVal.Field(i)
|
||||
fields = append(fields, field{fieldType, structVal.Field(i)})
|
||||
}
|
||||
}
|
||||
|
||||
for fieldType, field := range fields {
|
||||
fieldName := fieldType.Name
|
||||
// for fieldType, field := range fields {
|
||||
for _, f := range fields {
|
||||
field, fieldValue := f.field, f.val
|
||||
fieldName := field.Name
|
||||
|
||||
tagValue := fieldType.Tag.Get(d.config.TagName)
|
||||
tagValue := field.Tag.Get(d.config.TagName)
|
||||
tagValue = strings.SplitN(tagValue, ",", 2)[0]
|
||||
if tagValue != "" {
|
||||
fieldName = tagValue
|
||||
|
@ -653,7 +821,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
if !rawMapVal.IsValid() {
|
||||
// Do a slower search by iterating over each key and
|
||||
// doing case-insensitive search.
|
||||
for dataValKey, _ := range dataValKeys {
|
||||
for dataValKey := range dataValKeys {
|
||||
mK, ok := dataValKey.Interface().(string)
|
||||
if !ok {
|
||||
// Not a string key
|
||||
|
@ -677,14 +845,14 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
// Delete the key we're using from the unused map so we stop tracking
|
||||
delete(dataValKeysUnused, rawMapKey.Interface())
|
||||
|
||||
if !field.IsValid() {
|
||||
if !fieldValue.IsValid() {
|
||||
// This should never happen
|
||||
panic("field is not valid")
|
||||
}
|
||||
|
||||
// If we can't set the field, then it is unexported or something,
|
||||
// and we just continue onwards.
|
||||
if !field.CanSet() {
|
||||
if !fieldValue.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -694,14 +862,14 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
fieldName = fmt.Sprintf("%s.%s", name, fieldName)
|
||||
}
|
||||
|
||||
if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil {
|
||||
if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
|
||||
errors = appendErrors(errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
|
||||
keys := make([]string, 0, len(dataValKeysUnused))
|
||||
for rawKey, _ := range dataValKeysUnused {
|
||||
for rawKey := range dataValKeysUnused {
|
||||
keys = append(keys, rawKey.(string))
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
@ -716,7 +884,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||
|
||||
// Add the unused keys to the list of unused keys if we're tracking metadata
|
||||
if d.config.Metadata != nil {
|
||||
for rawKey, _ := range dataValKeysUnused {
|
||||
for rawKey := range dataValKeysUnused {
|
||||
key := rawKey.(string)
|
||||
if name != "" {
|
||||
key = fmt.Sprintf("%s.%s", name, key)
|
||||
|
|
|
@ -790,6 +790,30 @@
|
|||
"path": "github.com/hashicorp/go-multierror",
|
||||
"revision": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Nf2Gdn9M1KlUS3sovKfymO1VJF4=",
|
||||
"path": "github.com/hashicorp/go-oracle-terraform",
|
||||
"revision": "5a9a298c54339d2296d2f1135eae55a3a8f5e8c2",
|
||||
"revisionTime": "2018-01-11T20:31:13Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "hjQfXn32Tvuu6IJACOTsMzm+AbA=",
|
||||
"path": "github.com/hashicorp/go-oracle-terraform/client",
|
||||
"revision": "5a9a298c54339d2296d2f1135eae55a3a8f5e8c2",
|
||||
"revisionTime": "2018-01-11T20:31:13Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "wce86V0j11J6xRSvJEanprjK7so=",
|
||||
"path": "github.com/hashicorp/go-oracle-terraform/compute",
|
||||
"revision": "5a9a298c54339d2296d2f1135eae55a3a8f5e8c2",
|
||||
"revisionTime": "2018-01-11T20:31:13Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "NuObCk0/ybL3w++EnltgrB1GQRc=",
|
||||
"path": "github.com/hashicorp/go-oracle-terraform/opc",
|
||||
"revision": "5a9a298c54339d2296d2f1135eae55a3a8f5e8c2",
|
||||
"revisionTime": "2018-01-11T20:31:13Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ErJHGU6AVPZM9yoY/xV11TwSjQs=",
|
||||
"path": "github.com/hashicorp/go-retryablehttp",
|
||||
|
@ -957,9 +981,10 @@
|
|||
"revision": "87b45ffd0e9581375c491fef3d32130bb15c5bd7"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "4Js6Jlu93Wa0o6Kjt393L9Z7diE=",
|
||||
"checksumSHA1": "1JtAhgmRN0x794LRNhs0DJ5t8io=",
|
||||
"path": "github.com/mitchellh/mapstructure",
|
||||
"revision": "281073eb9eb092240d33ef253c404f1cca550309"
|
||||
"revision": "b4575eea38cca1123ec2dc90c26529b5c5acfcff",
|
||||
"revisionTime": "2018-01-11T00:07:20Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "m2L8ohfZiFRsMW3iynaH/TWgnSY=",
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
description:
|
||||
The oracle-classic builder is able to create new custom images for use with Oracle
|
||||
Compute Cloud.
|
||||
layout: docs
|
||||
page_title: 'Oracle Cloud Infrastructure Classic - Builders'
|
||||
sidebar_current: 'docs-builders-oracle-classic'
|
||||
---
|
||||
|
||||
# Oracle Cloud Infrastructure Classic Compute Builder
|
||||
|
||||
Type: `oracle-classic`
|
||||
|
||||
The `oracle-classic` Packer builder is able to create custom images for use
|
||||
with [Oracle Cloud Infrastructure Classic Compute](https://cloud.oracle.com/compute-classic). The builder
|
||||
takes a base image, runs any provisioning necessary on the base image after
|
||||
launching it, and finally snapshots it creating a reusable custom image.
|
||||
|
||||
It is recommended that you familiarise yourself with the
|
||||
[Key Concepts and Terminology](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/terminology.html)
|
||||
prior to using this builder if you have not done so already.
|
||||
|
||||
The builder _does not_ manage images. Once it creates an image, it is up to you
|
||||
to use it or delete it.
|
||||
|
||||
## Authorization
|
||||
|
||||
This builder authenticates API calls to Oracle Cloud Infrastructure Classic Compute using basic
|
||||
authentication (user name and password).
|
||||
To read more, see the [authentication documentation](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsa/Authentication.html)
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
There are many configuration options available for the `oracle-classic` builder.
|
||||
This builder currently only works with the SSH communicator.
|
||||
|
||||
### Required
|
||||
|
||||
- `api_endpoint` (string) - This is your custom API endpoint for sending
|
||||
requests. Instructions for determining your API endpoint can be found
|
||||
[here](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsa/SendRequests.html)
|
||||
|
||||
- `dest_image_list` (string) - Where to save the machine image to once you've
|
||||
provisioned it. If the provided image list does not exist, Packer will create it.
|
||||
|
||||
- `identity_domain` (string) - This is your customer-specific identity domain
|
||||
as generated by Oracle. If you don't know what your identity domain is, ask
|
||||
your account administrator. For a little more information, see the Oracle
|
||||
[documentation](https://docs.oracle.com/en/cloud/get-started/subscriptions-cloud/ocuid/identity-domain-overview.html#GUID-7969F881-5F4D-443E-B86C-9044C8085B8A).
|
||||
|
||||
- `source_image_list` (string) - This is what image you want to use as your base image.
|
||||
See the [documentation](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/listing-machine-images.html)
|
||||
for more details. You may use either a public image list, or a private image list. To see what public image lists are available, you can use
|
||||
the CLI, as described [here](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stopc/image-lists-stclr-and-nmcli.html#GUID-DB7E75FE-F752-4FF7-AB70-3C8DCDFCA0FA)
|
||||
|
||||
- `password` (string) - Your account password.
|
||||
|
||||
- `shape` (string) - The template that determines the number of
|
||||
CPUs, amount of memory, and other resources allocated to a newly created
|
||||
instance. For more information about shapes, see the documentation [here](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/machine-images-and-shapes.html).
|
||||
|
||||
- `username` (string) - Your account username.
|
||||
|
||||
### Optional
|
||||
|
||||
- `image_description` (string) - a description for your destination
|
||||
image list. If you don't provide one, Packer will provide a generic description.
|
||||
|
||||
- `ssh_username` (string) - The username that Packer will use to SSH into the
|
||||
instance; defaults to `opc`, the default oracle user, which has sudo
|
||||
priveliges. If you have already configured users on your machine, you may
|
||||
prompt Packer to use one of those instead. For more detail, see the
|
||||
[documentation](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/accessing-oracle-linux-instance-using-ssh.html).
|
||||
|
||||
- `image_name` (string) - The name to assign to the resulting custom image.
|
||||
|
||||
## Basic Example
|
||||
|
||||
Here is a basic example. Note that account specific configuration has been
|
||||
obfuscated; you will need to add a working `username`, `password`,
|
||||
`identity_domain`, and `api_endpoint` in order for the example to work.
|
||||
|
||||
``` {.json}
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "oracle-classic",
|
||||
"username": "myuser@myaccount.com",
|
||||
"password": "supersecretpasswordhere",
|
||||
"identity_domain": "#######",
|
||||
"api_endpoint": "https://api-###.compute.###.oraclecloud.com/",
|
||||
"source_image_list": "/oracle/public/OL_7.2_UEKR4_x86_64",
|
||||
"shape": "oc3",
|
||||
"image_name": "Packer_Builder_Test_{{timestamp}}"
|
||||
"dest_image_list": "Packer_Builder_Test_List"
|
||||
}
|
||||
],
|
||||
"provisioners": [
|
||||
{
|
||||
"type": "shell",
|
||||
"inline": ["echo hello"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
|
@ -131,6 +131,9 @@
|
|||
<li<%= sidebar_current("docs-builders-openstack") %>>
|
||||
<a href="/docs/builders/openstack.html">OpenStack</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-builders-oracle-classic") %>>
|
||||
<a href="/docs/builders/oracle-classic.html">Oracle Classic</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-builders-oracle-oci") %>>
|
||||
<a href="/docs/builders/oracle-oci.html">Oracle OCI</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue