Update oracle SDK

This commit is contained in:
Matthew Hooker 2018-10-24 14:04:51 -07:00
parent bbb0d450f1
commit ab723eaf78
No known key found for this signature in database
GPG Key ID: 7B5F933D9CE8C6A1
40 changed files with 1423 additions and 601 deletions

View File

@ -5,16 +5,20 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"math/rand"
"mime/multipart"
"net/http"
"net/url"
"runtime"
"strings"
"time"
"github.com/hashicorp/go-oracle-terraform/opc"
)
const DEFAULT_MAX_RETRIES = 1
const USER_AGENT_HEADER = "User-Agent"
const defaultMaxRetries = 1
const userAgentHeader = "User-Agent"
var (
// defaultUserAgent builds a string containing the Go version, system archityecture and OS,
@ -40,6 +44,7 @@ type Client struct {
loglevel opc.LogLevelType
}
// NewClient returns a new client
func NewClient(c *opc.Config) (*Client, error) {
// First create a client
client := &Client{
@ -71,7 +76,7 @@ func NewClient(c *opc.Config) (*Client, error) {
// Default max retries if unset
if c.MaxRetries == nil {
client.MaxRetries = opc.Int(DEFAULT_MAX_RETRIES)
client.MaxRetries = opc.Int(defaultMaxRetries)
}
// Protect against any nil http client
@ -82,7 +87,7 @@ func NewClient(c *opc.Config) (*Client, error) {
return client, nil
}
// Marshalls the request body and returns the resulting byte slice
// MarshallRequestBody 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.
@ -95,7 +100,7 @@ func (c *Client) MarshallRequestBody(body interface{}) ([]byte, error) {
return json.Marshal(body)
}
// Builds an HTTP Request that accepts a pre-marshaled body parameter as a raw byte array
// BuildRequestBody 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
@ -115,13 +120,13 @@ func (c *Client) BuildRequestBody(method, path string, body []byte) (*http.Reque
return nil, err
}
// Adding UserAgent Header
req.Header.Add(USER_AGENT_HEADER, *c.UserAgent)
req.Header.Add(userAgentHeader, *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) {
// BuildNonJSONRequest builds a new HTTP request that doesn't marshall the request body
func (c *Client) BuildNonJSONRequest(method, path string, body io.Reader) (*http.Request, error) {
// Parse URL Path
urlPath, err := url.Parse(path)
if err != nil {
@ -134,12 +139,56 @@ func (c *Client) BuildNonJSONRequest(method, path string, body io.ReadSeeker) (*
return nil, err
}
// Adding UserAgentHeader
req.Header.Add(USER_AGENT_HEADER, *c.UserAgent)
req.Header.Add(userAgentHeader, *c.UserAgent)
return req, nil
}
// This method executes the http.Request from the BuildRequest method.
// BuildMultipartFormRequest builds a new HTTP Request for a multipart form request from specifies attributes
func (c *Client) BuildMultipartFormRequest(method, path string, files map[string][]byte, parameters map[string]interface{}) (*http.Request, error) {
urlPath, err := url.Parse(path)
if err != nil {
return nil, err
}
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
var (
part io.Writer
)
for fileName, fileContents := range files {
part, err = writer.CreateFormFile(fileName, fmt.Sprintf("%s.json", fileName))
if err != nil {
return nil, err
}
_, err = part.Write(fileContents)
if err != nil {
return nil, err
}
}
// Add additional parameters to the writer
for key, val := range parameters {
if val.(string) != "" {
_ = writer.WriteField(key, val.(string))
}
}
err = writer.Close()
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, c.formatURL(urlPath), body)
req.Header.Set("Content-Type", writer.FormDataContentType())
return req, err
}
// ExecuteRequest 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
@ -161,7 +210,10 @@ func (c *Client) ExecuteRequest(req *http.Request) (*http.Response, error) {
// 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)
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return resp, nil
}
oracleErr.Message = buf.String()
}
@ -177,7 +229,7 @@ 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
retries = defaultMaxRetries
} else {
retries = *c.MaxRetries
}
@ -185,7 +237,28 @@ func (c *Client) retryRequest(req *http.Request) (*http.Response, error) {
var statusCode int
var errMessage string
for i := 0; i < retries; i++ {
// Cache the body content for retries.
// This is to allow reuse of the original request for the retries attempts
// as the act of reading the body (when doing the httpClient.Do()) closes the
// Reader.
var body []byte
if req.Body != nil {
var err error
body, err = ioutil.ReadAll(req.Body)
if err != nil {
return nil, err
}
}
// Initial sleep time between retries
sleep := 1 * time.Second
for i := retries; i > 0; i-- {
// replace body with new unread Reader before each request
if len(body) > 0 {
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
}
resp, err := c.httpClient.Do(req)
if err != nil {
return resp, err
@ -196,11 +269,23 @@ func (c *Client) retryRequest(req *http.Request) (*http.Response, error) {
}
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return resp, err
}
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))
c.DebugLogString(fmt.Sprintf("%s %s Encountered HTTP (%d) Error: %s", req.Method, req.URL, statusCode, errMessage))
if i != 1 {
c.DebugLogString(fmt.Sprintf("%d of %d retries remaining. Next retry in %ds", i-1, retries, sleep/time.Second))
time.Sleep(sleep)
// increase sleep time for next retry (exponential backoff with jitter)
// up to a maximum of ~60 seconds
if sleep <= 30*time.Second {
jitter := time.Duration(rand.Int63n(int64(sleep))) / 2
sleep = (sleep * 2) + jitter
}
}
}
oracleErr := &opc.OracleError{
@ -216,29 +301,32 @@ 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)
// WaitFor - Retry function
func (c *Client) WaitFor(description string, pollInterval, timeout time.Duration, test func() (bool, error)) error {
timeoutSeconds := int(timeout.Seconds())
pollIntervalSeconds := int(pollInterval.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
}
c.DebugLogString(fmt.Sprintf("Starting Wait For %s, polling every %d for %d seconds ", description, pollIntervalSeconds, timeoutSeconds))
for i := 0; i < timeoutSeconds; i += pollIntervalSeconds {
c.DebugLogString(fmt.Sprintf("Waiting %d seconds for %s (%d/%ds)", pollIntervalSeconds, description, i, timeoutSeconds))
time.Sleep(pollInterval)
completed, err := test()
if err != nil || completed {
return err
}
}
return fmt.Errorf("Timeout waiting for %s", description)
return fmt.Errorf("Timeout after %d seconds waiting for %s", timeoutSeconds, description)
}
// Used to determine if the checked resource was found or not.
// WasNotFoundError Used to determine if the checked resource was found or not.
func WasNotFoundError(e error) bool {
err, ok := e.(*opc.OracleError)
if ok {
if strings.Contains(err.Error(), "No such service exits") {
return true
}
return err.StatusCode == 404
}
return false

View File

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

View File

@ -6,20 +6,20 @@ type ACLsClient struct {
}
const (
ACLDescription = "acl"
ACLContainerPath = "/network/v1/acl/"
ACLResourcePath = "/network/v1/acl"
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 {
func (c *Client) ACLs() *ACLsClient {
return &ACLsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: ACLDescription,
ContainerPath: ACLContainerPath,
ResourceRootPath: ACLResourcePath,
Client: c,
ResourceDescription: aclDescription,
ContainerPath: aclContainerPath,
ResourceRootPath: aclResourcePath,
}}
}
@ -29,8 +29,10 @@ type ACLInfo struct {
Description string `json:"description"`
// Indicates whether the ACL is enabled
Enabled bool `json:"enabledFlag"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the ACL
Name string `json:"name"`
Name string
// Tags associated with the ACL
Tags []string `json:"tags"`
// Uniform Resource Identifier for the ACL
@ -133,6 +135,6 @@ func (c *ACLsClient) DeleteACL(deleteInput *DeleteACLInput) error {
}
func (c *ACLsClient) success(aclInfo *ACLInfo) (*ACLInfo, error) {
aclInfo.Name = c.getUnqualifiedName(aclInfo.Name)
aclInfo.Name = c.getUnqualifiedName(aclInfo.FQDN)
return aclInfo, nil
}

View File

@ -12,7 +12,7 @@ type AuthenticationReq struct {
}
// Get a new auth cookie for the compute client
func (c *ComputeClient) getAuthenticationCookie() error {
func (c *Client) getAuthenticationCookie() error {
req := AuthenticationReq{
User: c.getUserName(),
Password: *c.client.Password,

View File

@ -11,19 +11,20 @@ import (
"github.com/hashicorp/go-oracle-terraform/opc"
)
const CMP_ACME = "/Compute-%s"
const CMP_USERNAME = "/Compute-%s/%s"
const CMP_QUALIFIED_NAME = "%s/%s"
const cmpACME = "/Compute-%s"
const cmpUsername = "/Compute-%s/%s"
const cmpQualifiedName = "%s/%s"
// Client represents an authenticated compute client, with compute credentials and an api client.
type ComputeClient struct {
type Client struct {
client *client.Client
authCookie *http.Cookie
cookieIssued time.Time
}
func NewComputeClient(c *opc.Config) (*ComputeClient, error) {
computeClient := &ComputeClient{}
// NewComputeClient returns a compute client to interact with the Oracle Compute Infrastructure - Classic APIs
func NewComputeClient(c *opc.Config) (*Client, error) {
computeClient := &Client{}
client, err := client.NewClient(c)
if err != nil {
return nil, err
@ -37,7 +38,7 @@ func NewComputeClient(c *opc.Config) (*ComputeClient, error) {
return computeClient, nil
}
func (c *ComputeClient) executeRequest(method, path string, body interface{}) (*http.Response, error) {
func (c *Client) executeRequest(method, path string, body interface{}) (*http.Response, error) {
reqBody, err := c.client.MarshallRequestBody(body)
if err != nil {
return nil, err
@ -62,7 +63,7 @@ func (c *ComputeClient) executeRequest(method, path string, body interface{}) (*
if c.authCookie != nil {
if time.Since(c.cookieIssued).Minutes() > 25 {
c.authCookie = nil
if err := c.getAuthenticationCookie(); err != nil {
if err = c.getAuthenticationCookie(); err != nil {
return nil, err
}
}
@ -76,42 +77,42 @@ func (c *ComputeClient) executeRequest(method, path string, body interface{}) (*
return resp, nil
}
func (c *ComputeClient) getACME() string {
return fmt.Sprintf(CMP_ACME, *c.client.IdentityDomain)
func (c *Client) getACME() string {
return fmt.Sprintf(cmpACME, *c.client.IdentityDomain)
}
func (c *ComputeClient) getUserName() string {
return fmt.Sprintf(CMP_USERNAME, *c.client.IdentityDomain, *c.client.UserName)
func (c *Client) getUserName() string {
return fmt.Sprintf(cmpUsername, *c.client.IdentityDomain, *c.client.UserName)
}
func (c *ComputeClient) getQualifiedACMEName(name string) string {
func (c *Client) 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)
return fmt.Sprintf(cmpQualifiedName, 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 {
func (c *Client) getQualifiedName(name string) string {
if name == "" {
return ""
}
if strings.HasPrefix(name, "/oracle") || strings.HasPrefix(name, "/Compute-") {
return name
}
return fmt.Sprintf(CMP_QUALIFIED_NAME, c.getUserName(), name)
return fmt.Sprintf(cmpQualifiedName, c.getUserName(), name)
}
func (c *ComputeClient) getObjectPath(root, name string) string {
func (c *Client) getObjectPath(root, name string) string {
return fmt.Sprintf("%s%s", root, c.getQualifiedName(name))
}
// GetUnqualifiedName returns the unqualified name of an OPC object, e.g. the {name} part of /identity-domain/user@email/{name}
func (c *ComputeClient) getUnqualifiedName(name string) string {
func (c *Client) getUnqualifiedName(name string) string {
if name == "" {
return name
}
@ -126,40 +127,40 @@ func (c *ComputeClient) getUnqualifiedName(name string) string {
return strings.Join(nameParts[3:], "/")
}
func (c *ComputeClient) unqualify(names ...*string) {
func (c *Client) unqualify(names ...*string) {
for _, name := range names {
*name = c.getUnqualifiedName(*name)
}
}
func (c *ComputeClient) unqualifyUrl(url *string) {
func (c *Client) 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 {
func (c *Client) getQualifiedList(list []string) []string {
for i, name := range list {
list[i] = c.getQualifiedName(name)
}
return list
}
func (c *ComputeClient) getUnqualifiedList(list []string) []string {
func (c *Client) getUnqualifiedList(list []string) []string {
for i, name := range list {
list[i] = c.getUnqualifiedName(name)
}
return list
}
func (c *ComputeClient) getQualifiedListName(name string) string {
func (c *Client) getQualifiedListName(name string) string {
nameParts := strings.Split(name, ":")
listType := nameParts[0]
listName := nameParts[1]
return fmt.Sprintf("%s:%s", listType, c.getQualifiedName(listName))
}
func (c *ComputeClient) unqualifyListName(qualifiedName string) string {
func (c *Client) unqualifyListName(qualifiedName string) string {
nameParts := strings.Split(qualifiedName, ":")
listType := nameParts[0]
listName := nameParts[1]

View File

@ -11,7 +11,7 @@ import (
// ResourceClient is an AuthenticatedClient with some additional information about the resources to be addressed.
type ResourceClient struct {
*ComputeClient
*Client
ResourceDescription string
ContainerPath string
ResourceRootPath string
@ -58,12 +58,7 @@ func (c *ResourceClient) deleteResource(name string) error {
objectPath = c.ResourceRootPath
}
_, err := c.executeRequest("DELETE", objectPath, nil)
if err != nil {
return err
}
// No errors and no response body to write
return nil
return err
}
func (c *ResourceClient) deleteOrchestration(name string) error {
@ -77,22 +72,20 @@ func (c *ResourceClient) deleteOrchestration(name string) error {
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
return err
}
func (c *ResourceClient) unmarshalResponseBody(resp *http.Response, iface interface{}) error {
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
_, err := buf.ReadFrom(resp.Body)
if err != nil {
return err
}
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 {
if err = dcd.Decode(&tmp); err != nil {
return err
}

View File

@ -1,9 +1,9 @@
package compute
const (
ImageListDescription = "Image List"
ImageListContainerPath = "/imagelist/"
ImageListResourcePath = "/imagelist"
imageListDescription = "Image List"
imageListContainerPath = "/imagelist/"
imageListResourcePath = "/imagelist"
)
// ImageListClient is a client for the Image List functions of the Compute API.
@ -13,16 +13,17 @@ type ImageListClient struct {
// ImageList obtains an ImageListClient which can be used to access to the
// Image List functions of the Compute API
func (c *ComputeClient) ImageList() *ImageListClient {
func (c *Client) ImageList() *ImageListClient {
return &ImageListClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: ImageListDescription,
ContainerPath: ImageListContainerPath,
ResourceRootPath: ImageListResourcePath,
Client: c,
ResourceDescription: imageListDescription,
ContainerPath: imageListContainerPath,
ResourceRootPath: imageListResourcePath,
}}
}
// ImageListEntry details the attributes from an image list entry
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"`
@ -51,8 +52,11 @@ type ImageList struct {
// Each machine image in an image list is identified by an image list entry.
Entries []ImageListEntry `json:"entries"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the Image List
Name string `json:"name"`
Name string
// Uniform Resource Identifier
URI string `json:"uri"`
@ -86,7 +90,7 @@ func (c *ImageListClient) CreateImageList(createInput *CreateImageListInput) (*I
return c.success(&imageList)
}
// DeleteKeyInput describes the image list to delete
// DeleteImageListInput describes the image list to delete
type DeleteImageListInput struct {
// The name of the Image List
Name string `json:"name"`
@ -144,7 +148,7 @@ func (c *ImageListClient) UpdateImageList(updateInput *UpdateImageListInput) (*I
}
func (c *ImageListClient) success(imageList *ImageList) (*ImageList, error) {
c.unqualify(&imageList.Name)
imageList.Name = c.getUnqualifiedName(imageList.FQDN)
for _, v := range imageList.Entries {
v.MachineImages = c.getUnqualifiedList(v.MachineImages)

View File

@ -3,24 +3,25 @@ package compute
import "fmt"
const (
ImageListEntryDescription = "image list entry"
ImageListEntryContainerPath = "/imagelist"
ImageListEntryResourcePath = "/imagelist"
imageListEntryDescription = "image list entry"
imageListEntryContainerPath = "/imagelist"
imageListEntryResourcePath = "/imagelist"
)
// ImageListEntriesClient specifies the parameters for an image list entries client
type ImageListEntriesClient struct {
ResourceClient
}
// ImageListEntries() returns an ImageListEntriesClient that can be used to access the
// ImageListEntries returns an ImageListEntriesClient that can be used to access the
// necessary CRUD functions for Image List Entry's.
func (c *ComputeClient) ImageListEntries() *ImageListEntriesClient {
func (c *Client) ImageListEntries() *ImageListEntriesClient {
return &ImageListEntriesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: ImageListEntryDescription,
ContainerPath: ImageListEntryContainerPath,
ResourceRootPath: ImageListEntryResourcePath,
Client: c,
ResourceDescription: imageListEntryDescription,
ContainerPath: imageListEntryContainerPath,
ResourceRootPath: imageListEntryResourcePath,
},
}
}
@ -39,11 +40,12 @@ type ImageListEntryInfo struct {
// A list of machine images.
MachineImages []string `json:"machineimages"`
// Uniform Resource Identifier for the Image List Entry
Uri string `json:"uri"`
URI string `json:"uri"`
// Version number of these machineImages in the imagelist.
Version int `json:"version"`
}
// CreateImageListEntryInput specifies the parameters needed to creat an image list entry
type CreateImageListEntryInput struct {
// The name of the Image List
Name string
@ -62,7 +64,7 @@ type CreateImageListEntryInput struct {
Version int `json:"version"`
}
// Create a new Image List Entry from an ImageListEntriesClient and an input struct.
// CreateImageListEntry creates 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)
@ -73,6 +75,7 @@ func (c *ImageListEntriesClient) CreateImageListEntry(input *CreateImageListEntr
return c.success(&imageListEntryInfo)
}
// GetImageListEntryInput details the parameters needed to retrive an image list entry
type GetImageListEntryInput struct {
// The name of the Image List
Name string
@ -80,7 +83,7 @@ type GetImageListEntryInput struct {
Version int
}
// Returns a populated ImageListEntryInfo struct from an input struct
// GetImageListEntry 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
@ -90,6 +93,7 @@ func (c *ImageListEntriesClient) GetImageListEntry(input *GetImageListEntryInput
return c.success(&imageListEntryInfo)
}
// DeleteImageListEntryInput details the parameters needed to delete an image list entry
type DeleteImageListEntryInput struct {
// The name of the Image List
Name string
@ -97,6 +101,7 @@ type DeleteImageListEntryInput struct {
Version int
}
// DeleteImageListEntry deletes the specified image list entry
func (c *ImageListEntriesClient) DeleteImageListEntry(input *DeleteImageListEntryInput) error {
c.updateClientPaths(input.Name, input.Version)
return c.deleteResource("")
@ -105,8 +110,8 @@ func (c *ImageListEntriesClient) DeleteImageListEntry(input *DeleteImageListEntr
func (c *ImageListEntriesClient) updateClientPaths(name string, version int) {
var containerPath, resourcePath string
name = c.getQualifiedName(name)
containerPath = ImageListEntryContainerPath + name + "/entry/"
resourcePath = ImageListEntryContainerPath + name + "/entry"
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)
@ -117,6 +122,6 @@ func (c *ImageListEntriesClient) updateClientPaths(name string, version int) {
// Unqualifies any qualified fields in the IPNetworkInfo struct
func (c *ImageListEntriesClient) success(info *ImageListEntryInfo) (*ImageListEntryInfo, error) {
c.unqualifyUrl(&info.Uri)
c.unqualifyURL(&info.URI)
return info, nil
}

View File

@ -9,8 +9,10 @@ import (
"github.com/hashicorp/go-oracle-terraform/client"
)
const WaitForInstanceReadyTimeout = time.Duration(3600 * time.Second)
const WaitForInstanceDeleteTimeout = time.Duration(3600 * time.Second)
const waitForInstanceReadyPollInterval = 10 * time.Second
const waitForInstanceReadyTimeout = 3600 * time.Second
const waitForInstanceDeletePollInterval = 10 * time.Second
const waitForInstanceDeleteTimeout = 3600 * time.Second
// InstancesClient is a client for the Instance functions of the Compute API.
type InstancesClient struct {
@ -19,33 +21,45 @@ type InstancesClient struct {
// Instances obtains an InstancesClient which can be used to access to the
// Instance functions of the Compute API
func (c *ComputeClient) Instances() *InstancesClient {
func (c *Client) Instances() *InstancesClient {
return &InstancesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "instance",
ContainerPath: "/launchplan/",
ResourceRootPath: "/instance",
}}
}
// InstanceState specifies the constants that an instance state can be in
type InstanceState string
const (
InstanceRunning InstanceState = "running"
// InstanceRunning - running
InstanceRunning InstanceState = "running"
// InstanceInitializing - initializing
InstanceInitializing InstanceState = "initializing"
InstancePreparing InstanceState = "preparing"
InstanceStarting InstanceState = "starting"
InstanceStopping InstanceState = "stopping"
InstanceShutdown InstanceState = "shutdown"
InstanceQueued InstanceState = "queued"
InstanceError InstanceState = "error"
// InstancePreparing - preparing
InstancePreparing InstanceState = "preparing"
// InstanceStarting - starting
InstanceStarting InstanceState = "starting"
// InstanceStopping - stopping
InstanceStopping InstanceState = "stopping"
// InstanceShutdown - shutdown
InstanceShutdown InstanceState = "shutdown"
// InstanceQueued - queued
InstanceQueued InstanceState = "queued"
// InstanceError - error
InstanceError InstanceState = "error"
)
// InstanceDesiredState specifies the constants that for a desired instance state
type InstanceDesiredState string
const (
InstanceDesiredRunning InstanceDesiredState = "running"
// InstanceDesiredRunning - running
InstanceDesiredRunning InstanceDesiredState = "running"
// InstanceDesiredShutdown - shutdown
InstanceDesiredShutdown InstanceDesiredState = "shutdown"
)
@ -54,31 +68,24 @@ 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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The hostname for the instance
Hostname string `json:"hostname"`
@ -95,10 +102,7 @@ type InstanceInfo struct {
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"`
Name string
// A list of strings specifying arbitrary tags on nodes to be matched on placement.
PlacementRequirements []string `json:"placement_requirements"`
@ -118,9 +122,6 @@ type InstanceInfo struct {
// 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"`
@ -145,14 +146,31 @@ type InstanceInfo struct {
// vCable for this instance.
VCableID string `json:"vcable_id"`
// IP Address and port of the VNC console for the instance
VNC string `json:"vnc"`
// Add PTR records for the hostname
ReverseDNS bool `json:"reverse_dns"`
// 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"`
// Optional ImageListEntry number. Default will be used if not specified
Entry int `json:"entry"`
// Boot order list.
BootOrder []int `json:"boot_order"`
// 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"`
// Mapping of to network specifiers for virtual NICs to be attached to this instance.
Networking map[string]NetworkingInfo `json:"networking"`
}
// StorageAttachment specifies the parameters for a storage attachment
type StorageAttachment struct {
// The index number for the volume.
Index int `json:"index"`
@ -165,12 +183,11 @@ type StorageAttachment struct {
}
func (i *InstanceInfo) getInstanceName() string {
return fmt.Sprintf(CMP_QUALIFIED_NAME, i.Name, i.ID)
return fmt.Sprintf(cmpQualifiedName, i.Name, i.ID)
}
// CreateInstanceInput specifies the parameters needed to create an instance
type CreateInstanceInput struct {
// Optional ImageListEntry number. Default will be used if not specified
Entry int `json:"entry,omitempty"`
// A dictionary of user-defined attributes to be made available to the instance.
// Optional
Attributes map[string]interface{} `json:"attributes"`
@ -181,6 +198,9 @@ type CreateInstanceInput struct {
// Omits if empty.
// Optional
DesiredState InstanceDesiredState `json:"desired_state,omitempty"`
// ImageListEntry number. Default will be used if not specified
// Optional
Entry int `json:"entry,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
@ -220,6 +240,7 @@ type CreateInstanceInput struct {
Timeout time.Duration `json:"-"`
}
// StorageAttachmentInput specifies the attributes needed to attach a storage attachment
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.
@ -230,16 +251,21 @@ type StorageAttachmentInput struct {
Volume string `json:"volume"`
}
// ReservationPrefix - ipreservation
const ReservationPrefix = "ipreservation"
// ReservationIPPrefix - network/v1/ipreservation
const ReservationIPPrefix = "network/v1/ipreservation"
// NICModel specifies the constants that a nic model can be in
type NICModel string
const (
// NICDefaultModel - e1000
NICDefaultModel NICModel = "e1000"
)
// Struct of Networking info from a populated instance, or to be used as input to create an instance
// NetworkingInfo 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)
@ -293,20 +319,23 @@ type NetworkingInfo struct {
VnicSets []string `json:"vnicsets,omitempty"`
}
// LaunchPlan defines a launch plan, used to launch instances with the supplied InstanceSpec(s)
// LaunchPlanInput 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 between polls to check status
PollInterval time.Duration `json:"-"`
// Time to wait for instance boot
Timeout time.Duration `json:"-"`
}
// LaunchPlanResponse details the response recieved when submitting a launchplan
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.
// CreateInstance 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 {
@ -326,7 +355,7 @@ func (c *InstancesClient) CreateInstance(input *CreateInstanceInput) (*InstanceI
input.Networking = c.qualifyNetworking(input.Networking)
input.Name = fmt.Sprintf(CMP_QUALIFIED_NAME, c.getUserName(), input.Name)
input.Name = c.getQualifiedName(input.Name)
plan := LaunchPlanInput{
Instances: []CreateInstanceInput{*input},
@ -337,12 +366,12 @@ func (c *InstancesClient) CreateInstance(input *CreateInstanceInput) (*InstanceI
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))
for i := 0; i < *c.Client.client.MaxRetries; i++ {
c.client.DebugLogString(fmt.Sprintf("(Iteration: %d of %d) Creating instance with name %s\n Plan: %+v", i, *c.Client.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))
c.client.DebugLogString(fmt.Sprintf("(Iteration: %d of %d) Finished creating instance with name %s\n Info: %+v", i, *c.Client.client.MaxRetries, input.Name, instanceInfo))
return instanceInfo, nil
}
}
@ -366,14 +395,16 @@ func (c *InstancesClient) startInstance(name string, plan LaunchPlanInput) (*Ins
ID: responseBody.Instances[0].ID,
}
//timeout := WaitForInstanceReadyTimeout
if plan.PollInterval == 0 {
plan.PollInterval = waitForInstanceReadyPollInterval
}
if plan.Timeout == 0 {
plan.Timeout = WaitForInstanceReadyTimeout
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)
instanceInfo, instanceError := c.WaitForInstanceRunning(getInput, plan.PollInterval, plan.Timeout)
// If the instance enters an error state we need to delete the instance and retry
if instanceError != nil {
deleteInput := &DeleteInstanceInput{
@ -389,17 +420,18 @@ func (c *InstancesClient) startInstance(name string, plan LaunchPlanInput) (*Ins
return instanceInfo, nil
}
// Both of these fields are required. If they're not provided, things go wrong in
// incredibly amazing ways.
// GetInstanceInput specifies the parameters needed to retrieve an instance
type GetInstanceInput struct {
// The Unqualified Name of this Instance
// Required
Name string
// The Unqualified ID of this Instance
// Required
ID string
}
func (g *GetInstanceInput) String() string {
return fmt.Sprintf(CMP_QUALIFIED_NAME, g.Name, g.ID)
return fmt.Sprintf(cmpQualifiedName, g.Name, g.ID)
}
// GetInstance retrieves information about an instance.
@ -413,13 +445,13 @@ func (c *InstancesClient) GetInstance(input *GetInstanceInput) (*InstanceInfo, e
return nil, err
}
if responseBody.Name == "" {
if responseBody.FQDN == "" {
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), "/")
nID := strings.Split(c.getUnqualifiedName(responseBody.FQDN), "/")
responseBody.Name = nID[0]
responseBody.ID = nID[1]
@ -442,18 +474,20 @@ func (c *InstancesClient) GetInstance(input *GetInstanceInput) (*InstanceInfo, e
return &responseBody, nil
}
// InstancesInfo specifies a list of instances
type InstancesInfo struct {
Instances []InstanceInfo `json:"result"`
}
type GetInstanceIdInput struct {
// GetInstanceIDInput specifies the parameters needed to retrieve an instance
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) {
func (c *InstancesClient) GetInstanceFromName(input *GetInstanceIDInput) (*InstanceInfo, error) {
input.Name = c.getQualifiedName(input.Name)
var instancesInfo InstancesInfo
@ -462,14 +496,14 @@ func (c *InstancesClient) GetInstanceFromName(input *GetInstanceIdInput) (*Insta
}
for _, i := range instancesInfo.Instances {
if strings.Contains(i.Name, input.Name) {
if strings.Contains(i.FQDN, 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), "/")
nID := strings.Split(c.getUnqualifiedName(i.FQDN), "/")
i.Name = nID[0]
i.ID = nID[1]
@ -496,6 +530,7 @@ func (c *InstancesClient) GetInstanceFromName(input *GetInstanceIdInput) (*Insta
return nil, fmt.Errorf("Unable to find instance: %q", input.Name)
}
// UpdateInstanceInput specifies the parameters needed to update an instance
type UpdateInstanceInput struct {
// Name of this instance, generated by the server.
// Required
@ -510,20 +545,23 @@ type UpdateInstanceInput struct {
// A list of tags to be supplied to the instance
// Optional
Tags []string `json:"tags,omitempty"`
// Time to wait between polls for instance state
PollInterval time.Duration `json:"-"`
// 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)
return fmt.Sprintf(cmpQualifiedName, g.Name, g.ID)
}
// UpdateInstance updates an instance with the specified attributes
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)
input.Name = fmt.Sprintf(cmpQualifiedName, c.getUserName(), input.Name)
var responseBody InstanceInfo
if err := c.updateResource(input.String(), input, &responseBody); err != nil {
@ -535,8 +573,12 @@ func (c *InstancesClient) UpdateInstance(input *UpdateInstanceInput) (*InstanceI
ID: input.ID,
}
if input.PollInterval == 0 {
input.PollInterval = waitForInstanceReadyPollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForInstanceReadyTimeout
input.Timeout = waitForInstanceReadyTimeout
}
// Wait for the correct instance action depending on the current desired state.
@ -545,23 +587,25 @@ func (c *InstancesClient) UpdateInstance(input *UpdateInstanceInput) (*InstanceI
// 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)
return c.WaitForInstanceRunning(getInput, input.PollInterval, input.Timeout)
}
return c.WaitForInstanceShutdown(getInput, input.PollInterval, input.Timeout)
}
// DeleteInstanceInput specifies the parameters needed to delete an instance
type DeleteInstanceInput struct {
// The Unqualified Name of this Instance
Name string
// The Unqualified ID of this Instance
ID string
// Time to wait between polls to check status
PollInterval time.Duration
// 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)
return fmt.Sprintf(cmpQualifiedName, d.Name, d.ID)
}
// DeleteInstance deletes an instance.
@ -571,19 +615,22 @@ func (c *InstancesClient) DeleteInstance(input *DeleteInstanceInput) error {
return err
}
if input.PollInterval == 0 {
input.PollInterval = waitForInstanceDeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForInstanceDeleteTimeout
input.Timeout = waitForInstanceDeleteTimeout
}
// Wait for instance to be deleted
return c.WaitForInstanceDeleted(input, input.Timeout)
return c.WaitForInstanceDeleted(input, input.PollInterval, input.Timeout)
}
// WaitForInstanceRunning waits for an instance to be completely initialized and available.
func (c *InstancesClient) WaitForInstanceRunning(input *GetInstanceInput, timeout time.Duration) (*InstanceInfo, error) {
func (c *InstancesClient) WaitForInstanceRunning(input *GetInstanceInput, pollInterval, timeout time.Duration) (*InstanceInfo, error) {
var info *InstanceInfo
var getErr error
err := c.client.WaitFor("instance to be ready", timeout, func() (bool, error) {
err := c.client.WaitFor("instance to be ready", pollInterval, timeout, func() (bool, error) {
info, getErr = c.GetInstance(input)
if getErr != nil {
return false, getErr
@ -616,10 +663,10 @@ func (c *InstancesClient) WaitForInstanceRunning(input *GetInstanceInput, timeou
}
// WaitForInstanceShutdown waits for an instance to be shutdown
func (c *InstancesClient) WaitForInstanceShutdown(input *GetInstanceInput, timeout time.Duration) (*InstanceInfo, error) {
func (c *InstancesClient) WaitForInstanceShutdown(input *GetInstanceInput, pollInterval, timeout time.Duration) (*InstanceInfo, error) {
var info *InstanceInfo
var getErr error
err := c.client.WaitFor("instance to be shutdown", timeout, func() (bool, error) {
err := c.client.WaitFor("instance to be shutdown", pollInterval, timeout, func() (bool, error) {
info, getErr = c.GetInstance(input)
if getErr != nil {
return false, getErr
@ -654,8 +701,8 @@ func (c *InstancesClient) WaitForInstanceShutdown(input *GetInstanceInput, timeo
}
// 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) {
func (c *InstancesClient) WaitForInstanceDeleted(input fmt.Stringer, pollInterval, timeout time.Duration) error {
return c.client.WaitFor("instance to be deleted", pollInterval, timeout, func() (bool, error) {
var info InstanceInfo
if err := c.getResource(input.String(), &info); err != nil {
if client.WasNotFoundError(err) {
@ -699,13 +746,8 @@ func (c *InstancesClient) qualifyNetworking(info map[string]NetworkingInfo) map[
}
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
qfd.SecLists = c.getQualifiedList(v.SecLists)
}
qualifiedNetworks[k] = qfd
}
return qualifiedNetworks
@ -733,11 +775,7 @@ func (c *InstancesClient) unqualifyNetworking(info map[string]NetworkingInfo) (m
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
unq.SecLists = c.getUnqualifiedList(v.SecLists)
}
unqualifiedNetworks[k] = unq
}

View File

@ -1,24 +1,25 @@
package compute
const (
IPAddressAssociationDescription = "ip address association"
IPAddressAssociationContainerPath = "/network/v1/ipassociation/"
IPAddressAssociationResourcePath = "/network/v1/ipassociation"
iPAddressAssociationDescription = "ip address association"
iPAddressAssociationContainerPath = "/network/v1/ipassociation/"
iPAddressAssociationResourcePath = "/network/v1/ipassociation"
)
// IPAddressAssociationsClient details the parameters for an ip address association client
type IPAddressAssociationsClient struct {
ResourceClient
}
// IPAddressAssociations() returns an IPAddressAssociationsClient that can be used to access the
// IPAddressAssociations returns an IPAddressAssociationsClient that can be used to access the
// necessary CRUD functions for IP Address Associations.
func (c *ComputeClient) IPAddressAssociations() *IPAddressAssociationsClient {
func (c *Client) IPAddressAssociations() *IPAddressAssociationsClient {
return &IPAddressAssociationsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: IPAddressAssociationDescription,
ContainerPath: IPAddressAssociationContainerPath,
ResourceRootPath: IPAddressAssociationResourcePath,
Client: c,
ResourceDescription: iPAddressAssociationDescription,
ContainerPath: iPAddressAssociationContainerPath,
ResourceRootPath: iPAddressAssociationResourcePath,
},
}
}
@ -26,20 +27,23 @@ func (c *ComputeClient) IPAddressAssociations() *IPAddressAssociationsClient {
// IPAddressAssociationInfo contains the exported fields necessary to hold all the information about an
// IP Address Association
type IPAddressAssociationInfo struct {
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// 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"`
URI string `json:"uri"`
}
// CreateIPAddressAssociationInput details the attributes needed to create an ip address association
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.
@ -63,7 +67,7 @@ type CreateIPAddressAssociationInput struct {
Tags []string `json:"tags"`
}
// Create a new IP Address Association from an IPAddressAssociationsClient and an input struct.
// CreateIPAddressAssociation creates 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)
@ -78,13 +82,14 @@ func (c *IPAddressAssociationsClient) CreateIPAddressAssociation(input *CreateIP
return c.success(&ipInfo)
}
// GetIPAddressAssociationInput details the parameters needed to retrieve an ip address association
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
// GetIPAddressAssociation returns a populated IPAddressAssociationInfo struct from an input struct
func (c *IPAddressAssociationsClient) GetIPAddressAssociation(input *GetIPAddressAssociationInput) (*IPAddressAssociationInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -96,56 +101,21 @@ func (c *IPAddressAssociationsClient) GetIPAddressAssociation(input *GetIPAddres
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)
}
// DeleteIPAddressAssociationInput details the parameters neccessary to delete an ip address association
type DeleteIPAddressAssociationInput struct {
// The name of the IP Address Association to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteIPAddressAssociation deletes the specified ip address association
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)
info.Name = c.getUnqualifiedName(info.FQDN)
c.unqualify(&info.Vnic)
c.unqualify(&info.IPAddressReservation)
return info, nil

View File

@ -1,24 +1,25 @@
package compute
const (
IPAddressPrefixSetDescription = "ip address prefix set"
IPAddressPrefixSetContainerPath = "/network/v1/ipaddressprefixset/"
IPAddressPrefixSetResourcePath = "/network/v1/ipaddressprefixset"
iPAddressPrefixSetDescription = "ip address prefix set"
iPAddressPrefixSetContainerPath = "/network/v1/ipaddressprefixset/"
iPAddressPrefixSetResourcePath = "/network/v1/ipaddressprefixset"
)
// IPAddressPrefixSetsClient details the parameters for an ipaddress prefix set client
type IPAddressPrefixSetsClient struct {
ResourceClient
}
// IPAddressPrefixSets() returns an IPAddressPrefixSetsClient that can be used to access the
// IPAddressPrefixSets returns an IPAddressPrefixSetsClient that can be used to access the
// necessary CRUD functions for IP Address Prefix Sets.
func (c *ComputeClient) IPAddressPrefixSets() *IPAddressPrefixSetsClient {
func (c *Client) IPAddressPrefixSets() *IPAddressPrefixSetsClient {
return &IPAddressPrefixSetsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: IPAddressPrefixSetDescription,
ContainerPath: IPAddressPrefixSetContainerPath,
ResourceRootPath: IPAddressPrefixSetResourcePath,
Client: c,
ResourceDescription: iPAddressPrefixSetDescription,
ContainerPath: iPAddressPrefixSetContainerPath,
ResourceRootPath: iPAddressPrefixSetResourcePath,
},
}
}
@ -26,8 +27,10 @@ func (c *ComputeClient) IPAddressPrefixSets() *IPAddressPrefixSetsClient {
// IPAddressPrefixSetInfo contains the exported fields necessary to hold all the information about an
// IP Address Prefix Set
type IPAddressPrefixSetInfo struct {
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the IP Address Prefix Set
Name string `json:"name"`
Name string
// Description of the IP Address Prefix Set
Description string `json:"description"`
// List of CIDR IPv4 prefixes assigned in the virtual network.
@ -35,9 +38,10 @@ type IPAddressPrefixSetInfo struct {
// 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"`
URI string `json:"uri"`
}
// CreateIPAddressPrefixSetInput details the parameters to create an ip address prefix set
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.
@ -57,7 +61,7 @@ type CreateIPAddressPrefixSetInput struct {
Tags []string `json:"tags"`
}
// Create a new IP Address Prefix Set from an IPAddressPrefixSetsClient and an input struct.
// CreateIPAddressPrefixSet creates 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)
@ -70,13 +74,14 @@ func (c *IPAddressPrefixSetsClient) CreateIPAddressPrefixSet(input *CreateIPAddr
return c.success(&ipInfo)
}
// GetIPAddressPrefixSetInput details the parameters to retrieve an ip address prefix set
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
// GetIPAddressPrefixSet returns a populated IPAddressPrefixSetInfo struct from an input struct
func (c *IPAddressPrefixSetsClient) GetIPAddressPrefixSet(input *GetIPAddressPrefixSetInput) (*IPAddressPrefixSetInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -118,18 +123,20 @@ func (c *IPAddressPrefixSetsClient) UpdateIPAddressPrefixSet(updateInput *Update
return c.success(&ipInfo)
}
// DeleteIPAddressPrefixSetInput details the parameters to delete an ip address prefix set
type DeleteIPAddressPrefixSetInput struct {
// The name of the IP Address Prefix Set to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteIPAddressPrefixSet deletes the specified ip address prefix set
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)
info.Name = c.getUnqualifiedName(info.FQDN)
return info, nil
}

View File

@ -11,21 +11,21 @@ type IPAddressReservationsClient struct {
}
const (
IPAddressReservationDescription = "IP Address Reservation"
IPAddressReservationContainerPath = "/network/v1/ipreservation/"
IPAddressReservationResourcePath = "/network/v1/ipreservation"
IPAddressReservationQualifier = "/oracle/public"
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 {
func (c *Client) IPAddressReservations() *IPAddressReservationsClient {
return &IPAddressReservationsClient{
ResourceClient: &ResourceClient{
ComputeClient: c,
ResourceDescription: IPAddressReservationDescription,
ContainerPath: IPAddressReservationContainerPath,
ResourceRootPath: IPAddressReservationResourcePath,
Client: c,
ResourceDescription: iPAddressReservationDescription,
ContainerPath: iPAddressReservationContainerPath,
ResourceRootPath: iPAddressReservationResourcePath,
},
}
}
@ -35,6 +35,9 @@ type IPAddressReservation struct {
// Description of the IP Address Reservation
Description string `json:"description"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// Reserved NAT IPv4 address from the IP Address Pool
IPAddress string `json:"ipAddress"`
@ -42,17 +45,19 @@ type IPAddressReservation struct {
IPAddressPool string `json:"ipAddressPool"`
// Name of the reservation
Name string `json:"name"`
Name string
// Tags associated with the object
Tags []string `json:"tags"`
// Uniform Resource Identified for the reservation
Uri string `json:"uri"`
URI string `json:"uri"`
}
const (
PublicIPAddressPool = "public-ippool"
// PublicIPAddressPool - public-ippool
PublicIPAddressPool = "public-ippool"
// PrivateIPAddressPool - cloud-ippool
PrivateIPAddressPool = "cloud-ippool"
)
@ -81,7 +86,7 @@ type CreateIPAddressReservationInput struct {
Tags []string `json:"tags"`
}
// Takes an input struct, creates an IP Address reservation, and returns the info struct and any errors
// CreateIPAddressReservation 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
@ -98,14 +103,14 @@ func (c *IPAddressReservationsClient) CreateIPAddressReservation(input *CreateIP
return c.success(&ipAddrRes)
}
// Parameters to retrieve information on an ip address reservation
// GetIPAddressReservationInput details the 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
// GetIPAddressReservation returns an IP Address Reservation and any errors
func (c *IPAddressReservationsClient) GetIPAddressReservation(input *GetIPAddressReservationInput) (*IPAddressReservation, error) {
var ipAddrRes IPAddressReservation
@ -117,7 +122,7 @@ func (c *IPAddressReservationsClient) GetIPAddressReservation(input *GetIPAddres
return c.success(&ipAddrRes)
}
// Parameters to update an IP Address reservation
// UpdateIPAddressReservationInput details the parameters to update an IP Address reservation
type UpdateIPAddressReservationInput struct {
// Description of the IP Address Reservation
// Optional
@ -142,6 +147,7 @@ type UpdateIPAddressReservationInput struct {
Tags []string `json:"tags"`
}
// UpdateIPAddressReservation updates the specified ip address reservation
func (c *IPAddressReservationsClient) UpdateIPAddressReservation(input *UpdateIPAddressReservationInput) (*IPAddressReservation, error) {
var ipAddrRes IPAddressReservation
@ -159,19 +165,20 @@ func (c *IPAddressReservationsClient) UpdateIPAddressReservation(input *UpdateIP
return c.success(&ipAddrRes)
}
// Parameters to delete an IP Address Reservation
// DeleteIPAddressReservationInput details the parameters to delete an IP Address Reservation
type DeleteIPAddressReservationInput struct {
// The name of the reservation to delete
Name string `json:"name"`
}
// DeleteIPAddressReservation deletes the specified ip address reservation
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)
result.Name = c.getUnqualifiedName(result.FQDN)
if result.IPAddressPool != "" {
result.IPAddressPool = c.unqualifyIPAddressPool(result.IPAddressPool)
}
@ -181,7 +188,7 @@ func (c *IPAddressReservationsClient) success(result *IPAddressReservation) (*IP
func (c *IPAddressReservationsClient) qualifyIPAddressPool(input string) string {
// Add '/oracle/public/'
return fmt.Sprintf("%s/%s", IPAddressReservationQualifier, input)
return fmt.Sprintf("%s/%s", iPAddressReservationQualifier, input)
}
func (c *IPAddressReservationsClient) unqualifyIPAddressPool(input string) string {

View File

@ -12,10 +12,10 @@ type IPAssociationsClient struct {
// IPAssociations obtains a IPAssociationsClient which can be used to access to the
// IP Association functions of the Compute API
func (c *ComputeClient) IPAssociations() *IPAssociationsClient {
func (c *Client) IPAssociations() *IPAssociationsClient {
return &IPAssociationsClient{
ResourceClient: &ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "ip association",
ContainerPath: "/ip/association/",
ResourceRootPath: "/ip/association",
@ -26,8 +26,11 @@ func (c *ComputeClient) IPAssociations() *IPAssociationsClient {
type IPAssociationInfo struct {
// TODO: it'd probably make sense to expose the `ip` field here too?
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The three-part name of the object (/Compute-identity_domain/user/object).
Name string `json:"name"`
Name string
// 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.
@ -45,6 +48,7 @@ type IPAssociationInfo struct {
VCable string `json:"vcable"`
}
// CreateIPAssociationInput details the attributes neccessary to create an ip association
type CreateIPAssociationInput struct {
// The type of IP Address to associate with this instance
// for a Dynamic IP address specify `ippool:/oracle/public/ippool`.
@ -69,6 +73,7 @@ func (c *IPAssociationsClient) CreateIPAssociation(input *CreateIPAssociationInp
return c.success(&assocInfo)
}
// GetIPAssociationInput details the attributes neccessary to retrieve an ip association
type GetIPAssociationInput struct {
// The three-part name of the IP Association
// Required.
@ -85,6 +90,7 @@ func (c *IPAssociationsClient) GetIPAssociation(input *GetIPAssociationInput) (*
return c.success(&assocInfo)
}
// DeleteIPAssociationInput details the attributes neccessary to delete an ip association
type DeleteIPAssociationInput struct {
// The three-part name of the IP Association
// Required.
@ -112,7 +118,8 @@ func (c *IPAssociationsClient) unqualifyParentPoolName(parentpool *string) {
// Unqualifies identifiers
func (c *IPAssociationsClient) success(assocInfo *IPAssociationInfo) (*IPAssociationInfo, error) {
c.unqualify(&assocInfo.Name, &assocInfo.VCable)
assocInfo.Name = c.getUnqualifiedName(assocInfo.FQDN)
c.unqualify(&assocInfo.VCable)
c.unqualifyParentPoolName(&assocInfo.ParentPool)
return assocInfo, nil
}

View File

@ -1,24 +1,25 @@
package compute
const (
IPNetworkExchangeDescription = "ip network exchange"
IPNetworkExchangeContainerPath = "/network/v1/ipnetworkexchange/"
IPNetworkExchangeResourcePath = "/network/v1/ipnetworkexchange"
iPNetworkExchangeDescription = "ip network exchange"
iPNetworkExchangeContainerPath = "/network/v1/ipnetworkexchange/"
iPNetworkExchangeResourcePath = "/network/v1/ipnetworkexchange"
)
// IPNetworkExchangesClient details the ip network exchange client
type IPNetworkExchangesClient struct {
ResourceClient
}
// IPNetworkExchanges() returns an IPNetworkExchangesClient that can be used to access the
// IPNetworkExchanges returns an IPNetworkExchangesClient that can be used to access the
// necessary CRUD functions for IP Network Exchanges.
func (c *ComputeClient) IPNetworkExchanges() *IPNetworkExchangesClient {
func (c *Client) IPNetworkExchanges() *IPNetworkExchangesClient {
return &IPNetworkExchangesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: IPNetworkExchangeDescription,
ContainerPath: IPNetworkExchangeContainerPath,
ResourceRootPath: IPNetworkExchangeResourcePath,
Client: c,
ResourceDescription: iPNetworkExchangeDescription,
ContainerPath: iPNetworkExchangeContainerPath,
ResourceRootPath: iPNetworkExchangeResourcePath,
},
}
}
@ -26,16 +27,19 @@ func (c *ComputeClient) IPNetworkExchanges() *IPNetworkExchangesClient {
// IPNetworkExchangeInfo contains the exported fields necessary to hold all the information about an
// IP Network Exchange
type IPNetworkExchangeInfo struct {
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the IP Network Exchange
Name string `json:"name"`
Name string
// 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"`
URI string `json:"uri"`
}
// CreateIPNetworkExchangeInput details the attributes needed to create an ip network exchange
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.
@ -51,7 +55,7 @@ type CreateIPNetworkExchangeInput struct {
Tags []string `json:"tags"`
}
// Create a new IP Network Exchange from an IPNetworkExchangesClient and an input struct.
// CreateIPNetworkExchange creates 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)
@ -64,13 +68,14 @@ func (c *IPNetworkExchangesClient) CreateIPNetworkExchange(input *CreateIPNetwor
return c.success(&ipInfo)
}
// GetIPNetworkExchangeInput details the attributes needed to retrieve an ip network exchange
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
// GetIPNetworkExchange returns a populated IPNetworkExchangeInfo struct from an input struct
func (c *IPNetworkExchangesClient) GetIPNetworkExchange(input *GetIPNetworkExchangeInput) (*IPNetworkExchangeInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -82,18 +87,20 @@ func (c *IPNetworkExchangesClient) GetIPNetworkExchange(input *GetIPNetworkExcha
return c.success(&ipInfo)
}
// DeleteIPNetworkExchangeInput details the attributes neccessary to delete an ip network exchange
type DeleteIPNetworkExchangeInput struct {
// The name of the IP Network Exchange to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteIPNetworkExchange deletes the specified ip network exchange
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)
info.Name = c.getUnqualifiedName(info.FQDN)
return info, nil
}

View File

@ -1,24 +1,25 @@
package compute
const (
IPNetworkDescription = "ip network"
IPNetworkContainerPath = "/network/v1/ipnetwork/"
IPNetworkResourcePath = "/network/v1/ipnetwork"
iPNetworkDescription = "ip network"
iPNetworkContainerPath = "/network/v1/ipnetwork/"
iPNetworkResourcePath = "/network/v1/ipnetwork"
)
// IPNetworksClient specifies the ip networks client
type IPNetworksClient struct {
ResourceClient
}
// IPNetworks() returns an IPNetworksClient that can be used to access the
// IPNetworks returns an IPNetworksClient that can be used to access the
// necessary CRUD functions for IP Networks.
func (c *ComputeClient) IPNetworks() *IPNetworksClient {
func (c *Client) IPNetworks() *IPNetworksClient {
return &IPNetworksClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: IPNetworkDescription,
ContainerPath: IPNetworkContainerPath,
ResourceRootPath: IPNetworkResourcePath,
Client: c,
ResourceDescription: iPNetworkDescription,
ContainerPath: iPNetworkContainerPath,
ResourceRootPath: iPNetworkResourcePath,
},
}
}
@ -26,8 +27,10 @@ func (c *ComputeClient) IPNetworks() *IPNetworksClient {
// IPNetworkInfo contains the exported fields necessary to hold all the information about an
// IP Network
type IPNetworkInfo struct {
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the IP Network
Name string `json:"name"`
Name string
// The CIDR IPv4 prefix associated with the IP Network
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the IP Network Exchange associated with the IP Network
@ -39,9 +42,10 @@ type IPNetworkInfo struct {
// Slice of tags associated with the IP Network
Tags []string `json:"tags"`
// Uniform Resource Identifier for the IP Network
Uri string `json:"uri"`
URI string `json:"uri"`
}
// CreateIPNetworkInput details the attributes needed to create an ip network
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.
@ -83,7 +87,7 @@ type CreateIPNetworkInput struct {
Tags []string `json:"tags"`
}
// Create a new IP Network from an IPNetworksClient and an input struct.
// CreateIPNetwork creates 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)
@ -97,13 +101,14 @@ func (c *IPNetworksClient) CreateIPNetwork(input *CreateIPNetworkInput) (*IPNetw
return c.success(&ipInfo)
}
// GetIPNetworkInput details the attributes needed to retrieve an ip network
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
// GetIPNetwork returns a populated IPNetworkInfo struct from an input struct
func (c *IPNetworksClient) GetIPNetwork(input *GetIPNetworkInput) (*IPNetworkInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -115,6 +120,7 @@ func (c *IPNetworksClient) GetIPNetwork(input *GetIPNetworkInput) (*IPNetworkInf
return c.success(&ipInfo)
}
// UpdateIPNetworkInput details the attributes needed to update an ip network
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.
@ -156,6 +162,7 @@ type UpdateIPNetworkInput struct {
Tags []string `json:"tags"`
}
// UpdateIPNetwork updates the specified ip network
func (c *IPNetworksClient) UpdateIPNetwork(input *UpdateIPNetworkInput) (*IPNetworkInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.IPNetworkExchange = c.getQualifiedName(input.IPNetworkExchange)
@ -168,19 +175,21 @@ func (c *IPNetworksClient) UpdateIPNetwork(input *UpdateIPNetworkInput) (*IPNetw
return c.success(&ipInfo)
}
// DeleteIPNetworkInput specifies the attributes needed to delete an ip network
type DeleteIPNetworkInput struct {
// The name of the IP Network to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteIPNetwork deletes the specified ip network
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)
info.Name = c.getUnqualifiedName(info.FQDN)
c.unqualify(&info.IPNetworkExchange)
return info, nil
}

View File

@ -6,45 +6,49 @@ type IPReservationsClient struct {
}
const (
IPReservationDesc = "ip reservation"
IPReservationContainerPath = "/ip/reservation/"
IPReservataionResourcePath = "/ip/reservation"
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 {
func (c *Client) IPReservations() *IPReservationsClient {
return &IPReservationsClient{
ResourceClient: &ResourceClient{
ComputeClient: c,
ResourceDescription: IPReservationDesc,
ContainerPath: IPReservationContainerPath,
ResourceRootPath: IPReservataionResourcePath,
Client: c,
ResourceDescription: iPReservationDesc,
ContainerPath: iPReservationContainerPath,
ResourceRootPath: iPReservataionResourcePath,
}}
}
// IPReservationPool details the constants for the ip reservation pool attribute
type IPReservationPool string
const (
// PublicReservationPool - /oracle/public/ippool
PublicReservationPool IPReservationPool = "/oracle/public/ippool"
)
// IPReservationInput describes an existing IP reservation.
// IPReservation describes an existing IP reservation.
type IPReservation struct {
// Shows the default account for your identity domain.
Account string `json:"account"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// Public IP address.
IP string `json:"ip"`
// The three-part name of the IP Reservation (/Compute-identity_domain/user/object).
Name string `json:"name"`
Name string
// 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"`
URI string `json:"uri"`
// Is the IP Reservation Persistent (i.e. static) or not (i.e. Dynamic)?
Permanent bool `json:"permanent"`
// Is the IP reservation associated with an instance?
Used bool `json:"used"`
}
@ -142,6 +146,6 @@ func (c *IPReservationsClient) DeleteIPReservation(input *DeleteIPReservationInp
}
func (c *IPReservationsClient) success(result *IPReservation) (*IPReservation, error) {
c.unqualify(&result.Name)
result.Name = c.getUnqualifiedName(result.FQDN)
return result, nil
}

View File

@ -7,17 +7,17 @@ type MachineImagesClient struct {
// MachineImages obtains an MachineImagesClient which can be used to access to the
// MachineImage functions of the Compute API
func (c *ComputeClient) MachineImages() *MachineImagesClient {
func (c *Client) MachineImages() *MachineImagesClient {
return &MachineImagesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "MachineImage",
ContainerPath: "/machineimage/",
ResourceRootPath: "/machineimage",
}}
}
// MahineImage describes an existing Machine Image.
// MachineImage describes an existing Machine Image.
type MachineImage struct {
// account of the associated Object Storage Classic instance
Account string `json:"account"`
@ -34,6 +34,9 @@ type MachineImage struct {
// Description of the state of the machine image if there is an error
ErrorReason string `json:"error_reason"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// dictionary of hypervisor-specific attributes
Hypervisor map[string]interface{} `json:"hypervisor"`
@ -44,7 +47,7 @@ type MachineImage struct {
File string `json:"file"`
// name of the machine image
Name string `json:"name"`
Name string
// Indicates that the image file is available in Object Storage Classic
NoUpload bool `json:"no_upload"`
@ -117,7 +120,7 @@ func (c *MachineImagesClient) DeleteMachineImage(deleteInput *DeleteMachineImage
return c.deleteResource(deleteInput.Name)
}
// GetMachineList describes the MachineImage to get
// GetMachineImageInput describes the MachineImage to get
type GetMachineImageInput struct {
// account of the associated Object Storage Classic instance
Account string `json:"account"`
@ -138,6 +141,6 @@ func (c *MachineImagesClient) GetMachineImage(getInput *GetMachineImageInput) (*
}
func (c *MachineImagesClient) success(result *MachineImage) (*MachineImage, error) {
c.unqualify(&result.Name)
result.Name = c.getUnqualifiedName(result.FQDN)
return result, nil
}

View File

@ -7,8 +7,10 @@ import (
"github.com/hashicorp/go-oracle-terraform/client"
)
const WaitForOrchestrationActiveTimeout = time.Duration(3600 * time.Second)
const WaitForOrchestrationDeleteTimeout = time.Duration(3600 * time.Second)
const waitForOrchestrationActivePollInterval = 10 * time.Second
const waitForOrchestrationActiveTimeout = 3600 * time.Second
const waitForOrchestrationDeletePollInterval = 10 * time.Second
const waitForOrchestrationDeleteTimeout = 3600 * time.Second
// OrchestrationsClient is a client for the Orchestration functions of the Compute API.
type OrchestrationsClient struct {
@ -17,56 +19,73 @@ type OrchestrationsClient struct {
// Orchestrations obtains an OrchestrationsClient which can be used to access to the
// Orchestration functions of the Compute API
func (c *ComputeClient) Orchestrations() *OrchestrationsClient {
func (c *Client) Orchestrations() *OrchestrationsClient {
return &OrchestrationsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "Orchestration",
ContainerPath: "/platform/v1/orchestration/",
ResourceRootPath: "/platform/v1/orchestration",
}}
}
// OrchestrationDesiredState defines the different desired states a orchestration can be in
type OrchestrationDesiredState string
const (
// * active: Creates all the orchestration objects defined in the orchestration.
// OrchestrationDesiredStateActive - 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 - 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 - Suspends all orchestration objects defined in the orchestration
OrchestrationDesiredStateSuspend OrchestrationDesiredState = "suspend"
)
// OrchestrationStatus defines the different status a orchestration can be in
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"
// OrchestrationStatusActive - active
OrchestrationStatusActive OrchestrationStatus = "active"
// OrchestrationStatusInactive - inactive
OrchestrationStatusInactive OrchestrationStatus = "inactive"
// OrchestrationStatusSuspend - suspend
OrchestrationStatusSuspend OrchestrationStatus = "suspend"
// OrchestrationStatusActivating - activating
OrchestrationStatusActivating OrchestrationStatus = "activating"
// OrchestrationStatusDeleting - deleting
OrchestrationStatusDeleting OrchestrationStatus = "deleting"
// OrchestrationStatusError - terminal_error
OrchestrationStatusError OrchestrationStatus = "terminal_error"
// OrchestrationStatusStopping - stopping
OrchestrationStatusStopping OrchestrationStatus = "stopping"
// OrchestrationStatusSuspending - suspending
OrchestrationStatusSuspending OrchestrationStatus = "suspending"
// OrchestrationStatusStarting - starting
OrchestrationStatusStarting OrchestrationStatus = "starting"
// OrchestrationStatusDeactivating - deactivating
OrchestrationStatusDeactivating OrchestrationStatus = "deactivating"
OrchestrationStatusSuspended OrchestrationStatus = "suspended"
// OrchestrationStatusSuspended - suspended
OrchestrationStatusSuspended OrchestrationStatus = "suspended"
)
// OrchestrationType defines the type of orchestrations that can be managed
type OrchestrationType string
const (
// OrchestrationTypeInstance - Instance
OrchestrationTypeInstance OrchestrationType = "Instance"
)
// OrchestrationRelationshipType defines the orchestration relationship type for an orchestration
type OrchestrationRelationshipType string
const (
// OrchestrationRelationshipTypeDepends - the orchestration relationship depends on a resource
OrchestrationRelationshipTypeDepends OrchestrationRelationshipType = "depends"
)
// OrchestrationInfo describes an existing Orchestration.
// Orchestration describes an existing Orchestration.
type Orchestration struct {
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
Account string `json:"account"`
@ -76,8 +95,10 @@ type Orchestration struct {
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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The three-part name of the Orchestration
Name string
// List of orchestration objects
Objects []Object `json:"objects"`
// Current status of this orchestration
@ -125,10 +146,13 @@ type CreateOrchestrationInput struct {
Tags []string `json:"tags,omitempty"`
// Version of this orchestration. It is automatically generated by the server.
Version int `json:"version,omitempty"`
// Time to wait between polls to check status
PollInterval time.Duration `json:"-"`
// Time to wait for an orchestration to be ready
Timeout time.Duration `json:"-"`
}
// Object defines an object inside an orchestration
type Object struct {
// The default Oracle Compute Cloud Service account, such as /Compute-acme/default.
// Optional
@ -188,6 +212,7 @@ type Object struct {
Version int `json:"version,omitempty"`
}
// Health defines the health of an object
type Health struct {
// The status of the object
Status OrchestrationStatus `json:"status,omitempty"`
@ -199,6 +224,7 @@ type Health struct {
Error string `json:"error,omitempty"`
}
// Relationship defines the relationship between objects
type Relationship struct {
// The type of Relationship
// The only type is depends
@ -217,7 +243,7 @@ func (c *OrchestrationsClient) CreateOrchestration(input *CreateOrchestrationInp
for _, i := range input.Objects {
i.Orchestration = c.getQualifiedName(i.Orchestration)
if i.Type == OrchestrationTypeInstance {
instanceClient := c.ComputeClient.Instances()
instanceClient := c.Client.Instances()
instanceInput := i.Template.(*CreateInstanceInput)
instanceInput.Name = c.getQualifiedName(instanceInput.Name)
@ -251,13 +277,16 @@ func (c *OrchestrationsClient) CreateOrchestration(input *CreateOrchestrationInp
Name: createdOrchestration.Name,
}
if input.PollInterval == 0 {
input.PollInterval = waitForOrchestrationActivePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForOrchestrationActiveTimeout
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)
orchestrationInfo, orchestrationError := c.WaitForOrchestrationState(getInput, input.PollInterval, input.Timeout)
if orchestrationError != nil {
deleteInput := &DeleteOrchestrationInput{
Name: createdOrchestration.Name,
@ -269,7 +298,7 @@ func (c *OrchestrationsClient) CreateOrchestration(input *CreateOrchestrationInp
return nil, fmt.Errorf("Error creating orchestration %s: %s", getInput.Name, orchestrationError)
}
return &orchestrationInfo, nil
return orchestrationInfo, nil
}
// GetOrchestrationInput describes the Orchestration to get
@ -315,6 +344,8 @@ type UpdateOrchestrationInput struct {
Tags []string `json:"tags,omitempty"`
// Version of this orchestration. It is automatically generated by the server.
Version int `json:"version,omitempty"`
// Time to wait between polls to check status
PollInterval time.Duration `json:"-"`
// Time to wait for an orchestration to be ready
Timeout time.Duration `json:"-"`
}
@ -340,18 +371,21 @@ func (c *OrchestrationsClient) UpdateOrchestration(input *UpdateOrchestrationInp
Name: updatedOrchestration.Name,
}
if input.PollInterval == 0 {
input.PollInterval = waitForOrchestrationActivePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForOrchestrationActiveTimeout
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)
orchestrationInfo, orchestrationError := c.WaitForOrchestrationState(getInput, input.PollInterval, input.Timeout)
if orchestrationError != nil {
return nil, orchestrationError
}
return &orchestrationInfo, nil
return orchestrationInfo, nil
}
// DeleteOrchestrationInput describes the Orchestration to delete
@ -359,6 +393,8 @@ type DeleteOrchestrationInput struct {
// The three-part name of the Orchestration (/Compute-identity_domain/user/object).
// Required
Name string `json:"name"`
// Poll Interval for delete request
PollInterval time.Duration `json:"-"`
// Timeout for delete request
Timeout time.Duration `json:"-"`
}
@ -369,18 +405,21 @@ func (c *OrchestrationsClient) DeleteOrchestration(input *DeleteOrchestrationInp
return err
}
if input.PollInterval == 0 {
input.PollInterval = waitForOrchestrationDeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForOrchestrationDeleteTimeout
input.Timeout = waitForOrchestrationDeleteTimeout
}
return c.WaitForOrchestrationDeleted(input, input.Timeout)
return c.WaitForOrchestrationDeleted(input, input.PollInterval, input.Timeout)
}
func (c *OrchestrationsClient) success(info *Orchestration) (*Orchestration, error) {
c.unqualify(&info.Name)
info.Name = c.getUnqualifiedName(info.FQDN)
for _, i := range info.Objects {
c.unqualify(&i.Orchestration)
if OrchestrationType(i.Type) == OrchestrationTypeInstance {
if i.Type == OrchestrationTypeInstance {
instanceInput := i.Template.(map[string]interface{})
instanceInput["name"] = c.getUnqualifiedName(instanceInput["name"].(string))
}
@ -389,11 +428,11 @@ func (c *OrchestrationsClient) success(info *Orchestration) (*Orchestration, err
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) {
// WaitForOrchestrationState waits for an orchestration to be in the specified state
func (c *OrchestrationsClient) WaitForOrchestrationState(input *GetOrchestrationInput, pollInterval, timeout time.Duration) (*Orchestration, error) {
var info *Orchestration
var getErr error
err := c.client.WaitFor("orchestration to be ready", timeout, func() (bool, error) {
err := c.client.WaitFor("orchestration to be ready", pollInterval, timeout, func() (bool, error) {
info, getErr = c.GetOrchestration(input)
if getErr != nil {
return false, getErr
@ -427,19 +466,18 @@ func (c *OrchestrationsClient) WaitForOrchestrationState(input *GetOrchestration
c.client.DebugLogString("Orchestration suspended")
if info.DesiredState == OrchestrationDesiredStateSuspend {
return true, nil
} else {
return false, nil
}
return false, nil
default:
return false, fmt.Errorf("Unknown orchestration state: %s, erroring", s)
}
})
return *info, err
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) {
func (c *OrchestrationsClient) WaitForOrchestrationDeleted(input *DeleteOrchestrationInput, pollInterval, timeout time.Duration) error {
return c.client.WaitFor("orchestration to be deleted", pollInterval, timeout, func() (bool, error) {
var info Orchestration
if err := c.getResource(input.Name, &info); err != nil {
if client.WasNotFoundError(err) {

View File

@ -1,43 +1,49 @@
package compute
const (
RoutesDescription = "IP Network Route"
RoutesContainerPath = "/network/v1/route/"
RoutesResourcePath = "/network/v1/route"
routesDescription = "IP Network Route"
routesContainerPath = "/network/v1/route/"
routesResourcePath = "/network/v1/route"
)
// RoutesClient specifies the attributes of a route client
type RoutesClient struct {
ResourceClient
}
func (c *ComputeClient) Routes() *RoutesClient {
// Routes returns a route client
func (c *Client) Routes() *RoutesClient {
return &RoutesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: RoutesDescription,
ContainerPath: RoutesContainerPath,
ResourceRootPath: RoutesResourcePath,
Client: c,
ResourceDescription: routesDescription,
ContainerPath: routesContainerPath,
ResourceRootPath: routesResourcePath,
},
}
}
// RouteInfo details the attributes for a route
type RouteInfo struct {
// Admin distance associated with this route
AdminDistance int `json:"adminDistance"`
// Description of the route
Description string `json:"description"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// CIDR IPv4 Prefix associated with this route
IPAddressPrefix string `json:"ipAddressPrefix"`
// Name of the route
Name string `json:"name"`
Name string
// 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"`
URI string `json:"uri"`
}
// CreateRouteInput details the attributes needed to create a route
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.
@ -67,6 +73,7 @@ type CreateRouteInput struct {
Tags []string `json:"tags,omitempty"`
}
// CreateRoute creates the requested route
func (c *RoutesClient) CreateRoute(input *CreateRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.NextHopVnicSet = c.getQualifiedName(input.NextHopVnicSet)
@ -79,12 +86,14 @@ func (c *RoutesClient) CreateRoute(input *CreateRouteInput) (*RouteInfo, error)
return c.success(&routeInfo)
}
// GetRouteInput details the attributes needed to retrive a route
type GetRouteInput struct {
// Name of the Route to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// GetRoute retrieves the specified route
func (c *RoutesClient) GetRoute(input *GetRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -95,6 +104,7 @@ func (c *RoutesClient) GetRoute(input *GetRouteInput) (*RouteInfo, error) {
return c.success(&routeInfo)
}
// UpdateRouteInput details the attributes needed to update a route
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.
@ -124,6 +134,7 @@ type UpdateRouteInput struct {
Tags []string `json:"tags"`
}
// UpdateRoute updates the specified route
func (c *RoutesClient) UpdateRoute(input *UpdateRouteInput) (*RouteInfo, error) {
input.Name = c.getQualifiedName(input.Name)
input.NextHopVnicSet = c.getQualifiedName(input.NextHopVnicSet)
@ -136,18 +147,20 @@ func (c *RoutesClient) UpdateRoute(input *UpdateRouteInput) (*RouteInfo, error)
return c.success(&routeInfo)
}
// DeleteRouteInput details the route to delete
type DeleteRouteInput struct {
// Name of the Route to delete. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteRoute deletes the specified route
func (c *RoutesClient) DeleteRoute(input *DeleteRouteInput) error {
return c.deleteResource(input.Name)
}
func (c *RoutesClient) success(info *RouteInfo) (*RouteInfo, error) {
c.unqualify(&info.Name)
info.Name = c.getUnqualifiedName(info.FQDN)
c.unqualify(&info.NextHopVnicSet)
return info, nil
}

View File

@ -7,10 +7,10 @@ type SecRulesClient struct {
// SecRules obtains a SecRulesClient which can be used to access to the
// Sec Rules functions of the Compute API
func (c *ComputeClient) SecRules() *SecRulesClient {
func (c *Client) SecRules() *SecRulesClient {
return &SecRulesClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "security ip list",
ContainerPath: "/secrule/",
ResourceRootPath: "/secrule",
@ -29,8 +29,10 @@ type SecRuleInfo struct {
Disabled bool `json:"disabled"`
// The name of the destination security list or security IP list.
DestinationList string `json:"dst_list"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the sec rule
Name string `json:"name"`
Name string
// The name of the source security list or security IP list.
SourceList string `json:"src_list"`
// Uniform Resource Identifier for the sec rule
@ -185,7 +187,7 @@ func (c *SecRulesClient) DeleteSecRule(deleteInput *DeleteSecRuleInput) error {
}
func (c *SecRulesClient) success(ruleInfo *SecRuleInfo) (*SecRuleInfo, error) {
ruleInfo.Name = c.getUnqualifiedName(ruleInfo.Name)
ruleInfo.Name = c.getUnqualifiedName(ruleInfo.FQDN)
ruleInfo.SourceList = c.unqualifyListName(ruleInfo.SourceList)
ruleInfo.DestinationList = c.unqualifyListName(ruleInfo.DestinationList)
ruleInfo.Application = c.getUnqualifiedName(ruleInfo.Application)

View File

@ -7,10 +7,10 @@ type SecurityApplicationsClient struct {
// SecurityApplications obtains a SecurityApplicationsClient which can be used to access to the
// Security Application functions of the Compute API
func (c *ComputeClient) SecurityApplications() *SecurityApplicationsClient {
func (c *Client) SecurityApplications() *SecurityApplicationsClient {
return &SecurityApplicationsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "security application",
ContainerPath: "/secapplication/",
ResourceRootPath: "/secapplication",
@ -23,61 +23,92 @@ type SecurityApplicationInfo struct {
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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// The protocol to use.
Protocol SecurityApplicationProtocol `json:"protocol"`
// The Uniform Resource Identifier
URI string `json:"uri"`
}
// SecurityApplicationProtocol defines the constants for a security application protocol
type SecurityApplicationProtocol string
const (
All SecurityApplicationProtocol = "all"
AH SecurityApplicationProtocol = "ah"
ESP SecurityApplicationProtocol = "esp"
ICMP SecurityApplicationProtocol = "icmp"
// All - all
All SecurityApplicationProtocol = "all"
// AH - ah
AH SecurityApplicationProtocol = "ah"
// ESP - esp
ESP SecurityApplicationProtocol = "esp"
// ICMP - icmp
ICMP SecurityApplicationProtocol = "icmp"
// ICMPV6 - icmpv6
ICMPV6 SecurityApplicationProtocol = "icmpv6"
IGMP SecurityApplicationProtocol = "igmp"
IPIP SecurityApplicationProtocol = "ipip"
GRE SecurityApplicationProtocol = "gre"
// IGMP - igmp
IGMP SecurityApplicationProtocol = "igmp"
// IPIP - ipip
IPIP SecurityApplicationProtocol = "ipip"
// GRE - gre
GRE SecurityApplicationProtocol = "gre"
// MPLSIP - mplsip
MPLSIP SecurityApplicationProtocol = "mplsip"
OSPF SecurityApplicationProtocol = "ospf"
PIM SecurityApplicationProtocol = "pim"
RDP SecurityApplicationProtocol = "rdp"
SCTP SecurityApplicationProtocol = "sctp"
TCP SecurityApplicationProtocol = "tcp"
UDP SecurityApplicationProtocol = "udp"
// OSPF - ospf
OSPF SecurityApplicationProtocol = "ospf"
// PIM - pim
PIM SecurityApplicationProtocol = "pim"
// RDP - rdp
RDP SecurityApplicationProtocol = "rdp"
// SCTP - sctp
SCTP SecurityApplicationProtocol = "sctp"
// TCP - tcp
TCP SecurityApplicationProtocol = "tcp"
// UDP - udp
UDP SecurityApplicationProtocol = "udp"
)
// SecurityApplicationICMPCode defines the constants an icmp code can be
type SecurityApplicationICMPCode string
const (
Admin SecurityApplicationICMPCode = "admin"
Df SecurityApplicationICMPCode = "df"
Host SecurityApplicationICMPCode = "host"
Network SecurityApplicationICMPCode = "network"
Port SecurityApplicationICMPCode = "port"
// Admin - admin
Admin SecurityApplicationICMPCode = "admin"
// Df - df
Df SecurityApplicationICMPCode = "df"
// Host - host
Host SecurityApplicationICMPCode = "host"
// Network - network
Network SecurityApplicationICMPCode = "network"
// Port - port
Port SecurityApplicationICMPCode = "port"
// Protocol - protocol
Protocol SecurityApplicationICMPCode = "protocol"
)
// SecurityApplicationICMPType defines the constants an icmp type can be
type SecurityApplicationICMPType string
const (
Echo SecurityApplicationICMPType = "echo"
Reply SecurityApplicationICMPType = "reply"
TTL SecurityApplicationICMPType = "ttl"
TraceRoute SecurityApplicationICMPType = "traceroute"
// Echo - echo
Echo SecurityApplicationICMPType = "echo"
// Reply - reply
Reply SecurityApplicationICMPType = "reply"
// TTL - ttl
TTL SecurityApplicationICMPType = "ttl"
// TraceRoute - traceroute
TraceRoute SecurityApplicationICMPType = "traceroute"
// Unreachable - unreachable
Unreachable SecurityApplicationICMPType = "unreachable"
)
func (c *SecurityApplicationsClient) success(result *SecurityApplicationInfo) (*SecurityApplicationInfo, error) {
c.unqualify(&result.Name)
result.Name = c.getUnqualifiedName(result.FQDN)
return result, nil
}

View File

@ -7,10 +7,10 @@ type SecurityAssociationsClient struct {
// SecurityAssociations obtains a SecurityAssociationsClient which can be used to access to the
// Security Association functions of the Compute API
func (c *ComputeClient) SecurityAssociations() *SecurityAssociationsClient {
func (c *Client) SecurityAssociations() *SecurityAssociationsClient {
return &SecurityAssociationsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "security association",
ContainerPath: "/secassociation/",
ResourceRootPath: "/secassociation",
@ -19,8 +19,10 @@ func (c *ComputeClient) SecurityAssociations() *SecurityAssociationsClient {
// 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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The three-part name of the Security Association
Name string
// 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.
@ -90,6 +92,7 @@ func (c *SecurityAssociationsClient) DeleteSecurityAssociation(deleteInput *Dele
}
func (c *SecurityAssociationsClient) success(assocInfo *SecurityAssociationInfo) (*SecurityAssociationInfo, error) {
c.unqualify(&assocInfo.Name, &assocInfo.SecList, &assocInfo.VCable)
assocInfo.Name = c.getUnqualifiedName(assocInfo.FQDN)
c.unqualify(&assocInfo.SecList, &assocInfo.VCable)
return assocInfo, nil
}

View File

@ -7,10 +7,10 @@ type SecurityIPListsClient struct {
// 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 {
func (c *Client) SecurityIPLists() *SecurityIPListsClient {
return &SecurityIPListsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "security ip list",
ContainerPath: "/seciplist/",
ResourceRootPath: "/seciplist",
@ -21,8 +21,10 @@ func (c *ComputeClient) SecurityIPLists() *SecurityIPListsClient {
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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the object
Name string
// 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
@ -108,6 +110,6 @@ func (c *SecurityIPListsClient) DeleteSecurityIPList(deleteInput *DeleteSecurity
}
func (c *SecurityIPListsClient) success(listInfo *SecurityIPListInfo) (*SecurityIPListInfo, error) {
c.unqualify(&listInfo.Name)
listInfo.Name = c.getUnqualifiedName(listInfo.FQDN)
return listInfo, nil
}

View File

@ -7,21 +7,25 @@ type SecurityListsClient struct {
// SecurityLists obtains a SecurityListsClient which can be used to access to the
// Security List functions of the Compute API
func (c *ComputeClient) SecurityLists() *SecurityListsClient {
func (c *Client) SecurityLists() *SecurityListsClient {
return &SecurityListsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "security list",
ContainerPath: "/seclist/",
ResourceRootPath: "/seclist",
}}
}
// SecurityListPolicy defines the constants a security list policy can be
type SecurityListPolicy string
const (
SecurityListPolicyDeny SecurityListPolicy = "deny"
// SecurityListPolicyDeny - deny
SecurityListPolicyDeny SecurityListPolicy = "deny"
// SecurityListPolicyReject - reject
SecurityListPolicyReject SecurityListPolicy = "reject"
// SecurityListPolicyPermit - permit
SecurityListPolicyPermit SecurityListPolicy = "permit"
)
@ -31,8 +35,10 @@ type SecurityListInfo struct {
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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the security list
Name string
// The policy for outbound traffic from the security list.
OutboundCIDRPolicy SecurityListPolicy `json:"outbound_cidr_policy"`
// The policy for inbound traffic to the security list
@ -126,6 +132,6 @@ func (c *SecurityListsClient) DeleteSecurityList(deleteInput *DeleteSecurityList
}
func (c *SecurityListsClient) success(listInfo *SecurityListInfo) (*SecurityListInfo, error) {
c.unqualify(&listInfo.Name)
listInfo.Name = c.getUnqualifiedName(listInfo.FQDN)
return listInfo, nil
}

View File

@ -1,24 +1,25 @@
package compute
const (
SecurityProtocolDescription = "security protocol"
SecurityProtocolContainerPath = "/network/v1/secprotocol/"
SecurityProtocolResourcePath = "/network/v1/secprotocol"
securityProtocolDescription = "security protocol"
securityProtocolContainerPath = "/network/v1/secprotocol/"
securityProtocolResourcePath = "/network/v1/secprotocol"
)
// SecurityProtocolsClient details the security protocols client
type SecurityProtocolsClient struct {
ResourceClient
}
// SecurityProtocols() returns an SecurityProtocolsClient that can be used to access the
// SecurityProtocols returns an SecurityProtocolsClient that can be used to access the
// necessary CRUD functions for Security Protocols.
func (c *ComputeClient) SecurityProtocols() *SecurityProtocolsClient {
func (c *Client) SecurityProtocols() *SecurityProtocolsClient {
return &SecurityProtocolsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: SecurityProtocolDescription,
ContainerPath: SecurityProtocolContainerPath,
ResourceRootPath: SecurityProtocolResourcePath,
Client: c,
ResourceDescription: securityProtocolDescription,
ContainerPath: securityProtocolContainerPath,
ResourceRootPath: securityProtocolResourcePath,
},
}
}
@ -32,16 +33,19 @@ type SecurityProtocolInfo struct {
IPProtocol string `json:"ipProtocol"`
// List of port numbers or port range strings to match the packet's source port.
SrcPortSet []string `json:"srcPortSet"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the Security Protocol
Name string `json:"name"`
Name string
// 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"`
URI string `json:"uri"`
}
// CreateSecurityProtocolInput details the attributes of the security protocol to create
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.
@ -86,7 +90,7 @@ type CreateSecurityProtocolInput struct {
Tags []string `json:"tags"`
}
// Create a new Security Protocol from an SecurityProtocolsClient and an input struct.
// CreateSecurityProtocol creates 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)
@ -99,13 +103,14 @@ func (c *SecurityProtocolsClient) CreateSecurityProtocol(input *CreateSecurityPr
return c.success(&ipInfo)
}
// GetSecurityProtocolInput details the security protocol input to retrive
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
// GetSecurityProtocol returns a populated SecurityProtocolInfo struct from an input struct
func (c *SecurityProtocolsClient) GetSecurityProtocol(input *GetSecurityProtocolInput) (*SecurityProtocolInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -170,18 +175,20 @@ func (c *SecurityProtocolsClient) UpdateSecurityProtocol(updateInput *UpdateSecu
return c.success(&ipInfo)
}
// DeleteSecurityProtocolInput details the security protocal to delete
type DeleteSecurityProtocolInput struct {
// The name of the Security Protocol to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteSecurityProtocol deletes the specified security protocol
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)
info.Name = c.getUnqualifiedName(info.FQDN)
return info, nil
}

View File

@ -1,24 +1,25 @@
package compute
const (
SecurityRuleDescription = "security rules"
SecurityRuleContainerPath = "/network/v1/secrule/"
SecurityRuleResourcePath = "/network/v1/secrule"
securityRuleDescription = "security rules"
securityRuleContainerPath = "/network/v1/secrule/"
securityRuleResourcePath = "/network/v1/secrule"
)
// SecurityRuleClient defines the security rule client
type SecurityRuleClient struct {
ResourceClient
}
// SecurityRules() returns an SecurityRulesClient that can be used to access the
// SecurityRules returns an SecurityRulesClient that can be used to access the
// necessary CRUD functions for Security Rules.
func (c *ComputeClient) SecurityRules() *SecurityRuleClient {
func (c *Client) SecurityRules() *SecurityRuleClient {
return &SecurityRuleClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: SecurityRuleDescription,
ContainerPath: SecurityRuleContainerPath,
ResourceRootPath: SecurityRuleResourcePath,
Client: c,
ResourceDescription: securityRuleDescription,
ContainerPath: securityRuleContainerPath,
ResourceRootPath: securityRuleResourcePath,
},
}
}
@ -31,27 +32,30 @@ type SecurityRuleInfo struct {
// 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"`
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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// The name of the Security Rule
Name string `json:"name"`
Name string
// 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"`
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"`
URI string `json:"uri"`
}
// CreateSecurityRuleInput defines the attributes needed to create a security rule
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.
@ -67,7 +71,7 @@ type CreateSecurityRuleInput struct {
// When no destination IP address prefix sets are specified, traffic to any
// IP address is permitted.
// Optional
DstIpAddressPrefixSets []string `json:"dstIpAddressPrefixSets"`
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
@ -108,7 +112,7 @@ type CreateSecurityRuleInput struct {
// 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"`
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
@ -121,15 +125,15 @@ type CreateSecurityRuleInput struct {
Tags []string `json:"tags"`
}
// Create a new Security Rule from an SecurityRuleClient and an input struct.
// CreateSecurityRule creates 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.SrcIPAddressPrefixSets = c.getQualifiedList(input.SrcIPAddressPrefixSets)
input.DstIPAddressPrefixSets = c.getQualifiedList(input.DstIPAddressPrefixSets)
input.SecProtocols = c.getQualifiedList(input.SecProtocols)
var securityRuleInfo SecurityRuleInfo
@ -140,13 +144,14 @@ func (c *SecurityRuleClient) CreateSecurityRule(input *CreateSecurityRuleInput)
return c.success(&securityRuleInfo)
}
// GetSecurityRuleInput defines which security rule to obtain
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
// GetSecurityRule returns a populated SecurityRuleInfo struct from an input struct
func (c *SecurityRuleClient) GetSecurityRule(input *GetSecurityRuleInput) (*SecurityRuleInfo, error) {
input.Name = c.getQualifiedName(input.Name)
@ -174,7 +179,7 @@ type UpdateSecurityRuleInput struct {
// When no destination IP address prefix sets are specified, traffic to any
// IP address is permitted.
// Optional
DstIpAddressPrefixSets []string `json:"dstIpAddressPrefixSets"`
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
@ -215,7 +220,7 @@ type UpdateSecurityRuleInput struct {
// 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"`
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
@ -228,14 +233,14 @@ type UpdateSecurityRuleInput struct {
Tags []string `json:"tags"`
}
// UpdateSecRule modifies the properties of the sec rule with the given name.
// UpdateSecurityRule 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.SrcIPAddressPrefixSets = c.getQualifiedList(updateInput.SrcIPAddressPrefixSets)
updateInput.DstIPAddressPrefixSets = c.getQualifiedList(updateInput.DstIPAddressPrefixSets)
updateInput.SecProtocols = c.getQualifiedList(updateInput.SecProtocols)
var securityRuleInfo SecurityRuleInfo
@ -246,21 +251,24 @@ func (c *SecurityRuleClient) UpdateSecurityRule(updateInput *UpdateSecurityRuleI
return c.success(&securityRuleInfo)
}
// DeleteSecurityRuleInput specifies which security rule to delete
type DeleteSecurityRuleInput struct {
// The name of the Security Rule to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// DeleteSecurityRule deletes the specifies security rule
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.Name = c.getUnqualifiedName(info.FQDN)
c.unqualify(&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
}

View File

@ -5,7 +5,8 @@ import (
"time"
)
const WaitForSnapshotCompleteTimeout = time.Duration(600 * time.Second)
const waitForSnapshotCompletePollInterval = 30 * time.Second
const waitForSnapshotCompleteTimeout = 600 * time.Second
// SnapshotsClient is a client for the Snapshot functions of the Compute API.
type SnapshotsClient struct {
@ -14,32 +15,39 @@ type SnapshotsClient struct {
// Snapshots obtains an SnapshotsClient which can be used to access to the
// Snapshot functions of the Compute API
func (c *ComputeClient) Snapshots() *SnapshotsClient {
func (c *Client) Snapshots() *SnapshotsClient {
return &SnapshotsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "Snapshot",
ContainerPath: "/snapshot/",
ResourceRootPath: "/snapshot",
}}
}
// SnapshotState defines the constant states a snapshot can be in
type SnapshotState string
const (
SnapshotActive SnapshotState = "active"
// SnapshotActive - active
SnapshotActive SnapshotState = "active"
// SnapshotComplete - complete
SnapshotComplete SnapshotState = "complete"
SnapshotQueued SnapshotState = "queued"
SnapshotError SnapshotState = "error"
// SnapshotQueued - queued
SnapshotQueued SnapshotState = "queued"
// SnapshotError - error
SnapshotError SnapshotState = "error"
)
// SnapshotDelay defines the constant values snapshot delay can be
type SnapshotDelay string
const (
// SnapshotDelayShutdown - shutdown
SnapshotDelayShutdown SnapshotDelay = "shutdown"
)
// SnapshotInfo describes an existing Snapshot.
// Snapshot describes an existing Snapshot.
type Snapshot struct {
// Shows the default account for your identity domain.
Account string `json:"account"`
@ -49,12 +57,14 @@ type Snapshot struct {
Delay SnapshotDelay `json:"delay"`
// A description of the reason this request entered "error" state.
ErrorReason string `json:"error_reason"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// Not used
Quota string `json:"quota"`
// The state of the request.
@ -88,6 +98,8 @@ type CreateSnapshotInput struct {
// 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 between polling snapshot status
PollInterval time.Duration `json:"-"`
// Time to wait for snapshot to be completed
Timeout time.Duration `json:"-"`
}
@ -108,12 +120,15 @@ func (c *SnapshotsClient) CreateSnapshot(input *CreateSnapshotInput) (*Snapshot,
Name: snapshotInfo.Name,
}
if input.PollInterval == 0 {
input.PollInterval = waitForSnapshotCompletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForSnapshotCompleteTimeout
input.Timeout = waitForSnapshotCompleteTimeout
}
// Wait for snapshot to be complete and return the result
return c.WaitForSnapshotComplete(getInput, input.Timeout)
return c.WaitForSnapshotComplete(getInput, input.PollInterval, input.Timeout)
}
// GetSnapshotInput describes the snapshot to get
@ -142,6 +157,8 @@ type DeleteSnapshotInput struct {
// The name of the machine image
// Required
MachineImage string
// Time to wait between polls to check snapshot status
PollInterval time.Duration
// Time to wait for snapshot to be deleted
Timeout time.Duration
}
@ -154,11 +171,14 @@ func (c *SnapshotsClient) DeleteSnapshot(machineImagesClient *MachineImagesClien
Name: input.Snapshot,
}
if input.PollInterval == 0 {
input.PollInterval = waitForSnapshotCompletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForSnapshotCompleteTimeout
input.Timeout = waitForSnapshotCompleteTimeout
}
if _, err := c.WaitForSnapshotComplete(getInput, input.Timeout); err != nil {
if _, err := c.WaitForSnapshotComplete(getInput, input.PollInterval, input.Timeout); err != nil {
return fmt.Errorf("Could not delete snapshot: %s", err)
}
@ -186,11 +206,14 @@ func (c *SnapshotsClient) DeleteSnapshotResourceOnly(input *DeleteSnapshotInput)
Name: input.Snapshot,
}
if input.PollInterval == 0 {
input.PollInterval = waitForSnapshotCompletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForSnapshotCompleteTimeout
input.Timeout = waitForSnapshotCompleteTimeout
}
if _, err := c.WaitForSnapshotComplete(getInput, input.Timeout); err != nil {
if _, err := c.WaitForSnapshotComplete(getInput, input.PollInterval, input.Timeout); err != nil {
return fmt.Errorf("Could not delete snapshot: %s", err)
}
@ -202,10 +225,10 @@ func (c *SnapshotsClient) DeleteSnapshotResourceOnly(input *DeleteSnapshotInput)
}
// WaitForSnapshotComplete waits for an snapshot to be completely initialized and available.
func (c *SnapshotsClient) WaitForSnapshotComplete(input *GetSnapshotInput, timeout time.Duration) (*Snapshot, error) {
func (c *SnapshotsClient) WaitForSnapshotComplete(input *GetSnapshotInput, pollInterval, timeout time.Duration) (*Snapshot, error) {
var info *Snapshot
var getErr error
err := c.client.WaitFor("snapshot to be complete", timeout, func() (bool, error) {
err := c.client.WaitFor("snapshot to be complete", pollInterval, timeout, func() (bool, error) {
info, getErr = c.GetSnapshot(input)
if getErr != nil {
return false, getErr
@ -237,6 +260,6 @@ func (c *SnapshotsClient) success(snapshotInfo *Snapshot) (*Snapshot, error) {
c.unqualify(&snapshotInfo.Account)
c.unqualify(&snapshotInfo.Instance)
c.unqualify(&snapshotInfo.MachineImage)
c.unqualify(&snapshotInfo.Name)
snapshotInfo.Name = c.getUnqualifiedName(snapshotInfo.FQDN)
return snapshotInfo, nil
}

View File

@ -7,24 +7,26 @@ type SSHKeysClient struct {
// SSHKeys obtains an SSHKeysClient which can be used to access to the
// SSH key functions of the Compute API
func (c *ComputeClient) SSHKeys() *SSHKeysClient {
func (c *Client) SSHKeys() *SSHKeysClient {
return &SSHKeysClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "SSH key",
ContainerPath: "/sshkey/",
ResourceRootPath: "/sshkey",
}}
}
// SSHKeyInfo describes an existing SSH key.
// SSHKey describes an existing SSH key.
type SSHKey struct {
// Indicates whether the key is enabled (true) or disabled.
Enabled bool `json:"enabled"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// Unique Resource Identifier
URI string `json:"uri"`
}
@ -107,7 +109,7 @@ func (c *SSHKeysClient) UpdateSSHKey(updateInput *UpdateSSHKeyInput) (*SSHKey, e
return c.success(&keyInfo)
}
// DeleteKeyInput describes the ssh key to delete
// DeleteSSHKeyInput 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"`
@ -119,6 +121,6 @@ func (c *SSHKeysClient) DeleteSSHKey(deleteInput *DeleteSSHKeyInput) error {
}
func (c *SSHKeysClient) success(keyInfo *SSHKey) (*SSHKey, error) {
c.unqualify(&keyInfo.Name)
keyInfo.Name = c.getUnqualifiedName(keyInfo.FQDN)
return keyInfo, nil
}

View File

@ -6,8 +6,10 @@ import (
"github.com/hashicorp/go-oracle-terraform/client"
)
const WaitForVolumeAttachmentDeleteTimeout = time.Duration(30 * time.Second)
const WaitForVolumeAttachmentReadyTimeout = time.Duration(30 * time.Second)
const waitForVolumeAttachmentDeletePollInterval = 1 * time.Second
const waitForVolumeAttachmentDeleteTimeout = 30 * time.Second
const waitForVolumeAttachmentReadyPollInterval = 1 * time.Second
const waitForVolumeAttachmentReadyTimeout = 30 * time.Second
// StorageAttachmentsClient is a client for the Storage Attachment functions of the Compute API.
type StorageAttachmentsClient struct {
@ -16,30 +18,39 @@ type StorageAttachmentsClient struct {
// StorageAttachments obtains a StorageAttachmentsClient which can be used to access to the
// Storage Attachment functions of the Compute API
func (c *ComputeClient) StorageAttachments() *StorageAttachmentsClient {
func (c *Client) StorageAttachments() *StorageAttachmentsClient {
return &StorageAttachmentsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "storage volume attachment",
ContainerPath: "/storage/attachment/",
ResourceRootPath: "/storage/attachment",
}}
}
// StorageAttachmentState defines all the storage attachment states
type StorageAttachmentState string
const (
Attaching StorageAttachmentState = "attaching"
Attached StorageAttachmentState = "attached"
Detaching StorageAttachmentState = "detaching"
// Attaching - attaching
Attaching StorageAttachmentState = "attaching"
// Attached - attached
Attached StorageAttachmentState = "attached"
// Detaching - detaching
Detaching StorageAttachmentState = "detaching"
// Unavailable - unavailable
Unavailable StorageAttachmentState = "unavailable"
Unknown StorageAttachmentState = "unknown"
// Unknown - unkown
Unknown StorageAttachmentState = "unknown"
)
// StorageAttachmentInfo describes an existing storage attachment.
type StorageAttachmentInfo struct {
// Fully Qualified Domain Name
FQDN string `json:"name"`
// Name of this attachment, generated by the server.
Name string `json:"name"`
Name string
// 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.
@ -56,10 +67,12 @@ type StorageAttachmentInfo struct {
}
func (c *StorageAttachmentsClient) success(attachmentInfo *StorageAttachmentInfo) (*StorageAttachmentInfo, error) {
c.unqualify(&attachmentInfo.Name, &attachmentInfo.InstanceName, &attachmentInfo.StorageVolumeName)
attachmentInfo.Name = c.getQualifiedName(attachmentInfo.FQDN)
c.unqualify(&attachmentInfo.InstanceName, &attachmentInfo.StorageVolumeName)
return attachmentInfo, nil
}
// CreateStorageAttachmentInput defines the attributes to create a storage attachment
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.
@ -74,6 +87,9 @@ type CreateStorageAttachmentInput struct {
// Required.
StorageVolumeName string `json:"storage_volume_name"`
// Time to wait between polls to check volume attachment status
PollInterval time.Duration `json:"-"`
// Time to wait for storage volume attachment
Timeout time.Duration `json:"-"`
}
@ -88,11 +104,14 @@ func (c *StorageAttachmentsClient) CreateStorageAttachment(input *CreateStorageA
return nil, err
}
if input.PollInterval == 0 {
input.PollInterval = waitForVolumeAttachmentReadyPollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForVolumeAttachmentReadyTimeout
input.Timeout = waitForVolumeAttachmentReadyTimeout
}
return c.waitForStorageAttachmentToFullyAttach(attachmentInfo.Name, input.Timeout)
return c.waitForStorageAttachmentToFullyAttach(attachmentInfo.Name, input.PollInterval, input.Timeout)
}
// DeleteStorageAttachmentInput represents the body of an API request to delete a Storage Attachment.
@ -101,6 +120,9 @@ type DeleteStorageAttachmentInput struct {
// Required
Name string `json:"name"`
// Time to wait between polls to check volume attachment status
PollInterval time.Duration `json:"-"`
// Time to wait for storage volume snapshot
Timeout time.Duration `json:"-"`
}
@ -111,11 +133,14 @@ func (c *StorageAttachmentsClient) DeleteStorageAttachment(input *DeleteStorageA
return err
}
if input.PollInterval == 0 {
input.PollInterval = waitForVolumeAttachmentDeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForVolumeAttachmentDeleteTimeout
input.Timeout = waitForVolumeAttachmentDeleteTimeout
}
return c.waitForStorageAttachmentToBeDeleted(input.Name, input.Timeout)
return c.waitForStorageAttachmentToBeDeleted(input.Name, input.PollInterval, input.Timeout)
}
// GetStorageAttachmentInput represents the body of an API request to obtain a Storage Attachment.
@ -136,10 +161,10 @@ func (c *StorageAttachmentsClient) GetStorageAttachment(input *GetStorageAttachm
}
// 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) {
func (c *StorageAttachmentsClient) waitForStorageAttachmentToFullyAttach(name string, pollInterval, timeout time.Duration) (*StorageAttachmentInfo, error) {
var waitResult *StorageAttachmentInfo
err := c.client.WaitFor("storage attachment to be attached", timeout, func() (bool, error) {
err := c.client.WaitFor("storage attachment to be attached", pollInterval, timeout, func() (bool, error) {
input := &GetStorageAttachmentInput{
Name: name,
}
@ -162,8 +187,8 @@ func (c *StorageAttachmentsClient) waitForStorageAttachmentToFullyAttach(name st
}
// 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) {
func (c *StorageAttachmentsClient) waitForStorageAttachmentToBeDeleted(name string, pollInterval, timeout time.Duration) error {
return c.client.WaitFor("storage attachment to be deleted", pollInterval, timeout, func() (bool, error) {
input := &GetStorageAttachmentInput{
Name: name,
}

View File

@ -9,14 +9,16 @@ import (
)
const (
StorageVolumeSnapshotDescription = "storage volume snapshot"
StorageVolumeSnapshotContainerPath = "/storage/snapshot/"
StorageVolumeSnapshotResourcePath = "/storage/snapshot"
storageVolumeSnapshotDescription = "storage volume snapshot"
storageVolumeSnapshotContainerPath = "/storage/snapshot/"
storageVolumeSnapshotResourcePath = "/storage/snapshot"
WaitForSnapshotCreateTimeout = time.Duration(2400 * time.Second)
WaitForSnapshotDeleteTimeout = time.Duration(1500 * time.Second)
waitForSnapshotCreatePollInterval = 30 * time.Second
waitForSnapshotCreateTimeout = 2400 * time.Second
waitForSnapshotDeletePollInterval = 30 * time.Second
waitForSnapshotDeleteTimeout = 1500 * time.Second
// Collocated Snapshot Property
// SnapshotPropertyCollocated - Collocated Snapshot Property
SnapshotPropertyCollocated = "/oracle/private/storage/snapshot/collocated"
)
@ -25,13 +27,14 @@ type StorageVolumeSnapshotClient struct {
ResourceClient
}
func (c *ComputeClient) StorageVolumeSnapshots() *StorageVolumeSnapshotClient {
// StorageVolumeSnapshots returns a storage volume snapshot client
func (c *Client) StorageVolumeSnapshots() *StorageVolumeSnapshotClient {
return &StorageVolumeSnapshotClient{
ResourceClient: ResourceClient{
ComputeClient: c,
ResourceDescription: StorageVolumeSnapshotDescription,
ContainerPath: StorageVolumeSnapshotContainerPath,
ResourceRootPath: StorageVolumeSnapshotResourcePath,
Client: c,
ResourceDescription: storageVolumeSnapshotDescription,
ContainerPath: storageVolumeSnapshotContainerPath,
ResourceRootPath: storageVolumeSnapshotResourcePath,
},
}
}
@ -44,11 +47,14 @@ type StorageVolumeSnapshotInfo struct {
// Description of the snapshot
Description string `json:"description"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// String indicating whether the parent volume is bootable or not
ParentVolumeBootable string `json:"parent_volume_bootable"`
@ -116,6 +122,9 @@ type CreateStorageVolumeSnapshotInput struct {
// Required
Volume string `json:"volume"`
// Timeout to wait between polling snapshot status. Will use default if unspecified
PollInterval time.Duration `json:"-"`
// Timeout to wait for snapshot to be completed. Will use default if unspecified
Timeout time.Duration `json:"-"`
}
@ -132,12 +141,15 @@ func (c *StorageVolumeSnapshotClient) CreateStorageVolumeSnapshot(input *CreateS
return nil, err
}
if input.PollInterval == 0 {
input.PollInterval = waitForSnapshotCreatePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForSnapshotCreateTimeout
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)
return c.waitForStorageSnapshotAvailable(storageSnapshotInfo.Name, input.PollInterval, input.Timeout)
}
// GetStorageVolumeSnapshotInput represents the body of an API request to get information on a storage volume snapshot
@ -165,11 +177,14 @@ type DeleteStorageVolumeSnapshotInput struct {
// Name of the snapshot to delete
Name string `json:"name"`
// Timeout to wait between polling snapshot status, will use default if unspecified
PollInterval time.Duration `json:"-"`
// 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
// DeleteStorageVolumeSnapshot makes an API request to delete a storage volume snapshot
func (c *StorageVolumeSnapshotClient) DeleteStorageVolumeSnapshot(input *DeleteStorageVolumeSnapshotInput) error {
input.Name = c.getQualifiedName(input.Name)
@ -177,15 +192,18 @@ func (c *StorageVolumeSnapshotClient) DeleteStorageVolumeSnapshot(input *DeleteS
return err
}
if input.PollInterval == 0 {
input.PollInterval = waitForSnapshotDeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForSnapshotDeleteTimeout
input.Timeout = waitForSnapshotDeleteTimeout
}
return c.waitForStorageSnapshotDeleted(input.Name, input.Timeout)
return c.waitForStorageSnapshotDeleted(input.Name, input.PollInterval, input.Timeout)
}
func (c *StorageVolumeSnapshotClient) success(result *StorageVolumeSnapshotInfo) (*StorageVolumeSnapshotInfo, error) {
c.unqualify(&result.Name)
result.Name = c.getUnqualifiedName(result.FQDN)
c.unqualify(&result.Volume)
sizeInGigaBytes, err := sizeInGigaBytes(result.Size)
@ -198,11 +216,12 @@ func (c *StorageVolumeSnapshotClient) success(result *StorageVolumeSnapshotInfo)
}
// Waits for a storage snapshot to become available
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotAvailable(name string, timeout time.Duration) (*StorageVolumeSnapshotInfo, error) {
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotAvailable(name string, pollInterval, timeout time.Duration) (*StorageVolumeSnapshotInfo, error) {
var result *StorageVolumeSnapshotInfo
err := c.client.WaitFor(
fmt.Sprintf("storage volume snapshot %s to become available", c.getQualifiedName(name)),
pollInterval,
timeout,
func() (bool, error) {
req := &GetStorageVolumeSnapshotInput{
@ -229,9 +248,10 @@ func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotAvailable(name strin
}
// Waits for a storage snapshot to be deleted
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotDeleted(name string, timeout time.Duration) error {
func (c *StorageVolumeSnapshotClient) waitForStorageSnapshotDeleted(name string, pollInterval, timeout time.Duration) error {
return c.client.WaitFor(
fmt.Sprintf("storage volume snapshot %s to be deleted", c.getQualifiedName(name)),
pollInterval,
timeout,
func() (bool, error) {
req := &GetStorageVolumeSnapshotInput{

View File

@ -9,8 +9,10 @@ import (
"github.com/hashicorp/go-oracle-terraform/client"
)
const WaitForVolumeReadyTimeout = time.Duration(600 * time.Second)
const WaitForVolumeDeleteTimeout = time.Duration(600 * time.Second)
const waitForVolumeReadyPollInterval = 10 * time.Second
const waitForVolumeReadyTimeout = 600 * time.Second
const waitForVolumeDeletePollInterval = 10 * time.Second
const waitForVolumeDeleteTimeout = 600 * time.Second
// StorageVolumeClient is a client for the Storage Volume functions of the Compute API.
type StorageVolumeClient struct {
@ -19,10 +21,10 @@ type StorageVolumeClient struct {
// StorageVolumes obtains a StorageVolumeClient which can be used to access to the
// Storage Volume functions of the Compute API
func (c *ComputeClient) StorageVolumes() *StorageVolumeClient {
func (c *Client) StorageVolumes() *StorageVolumeClient {
return &StorageVolumeClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "storage volume",
ContainerPath: "/storage/volume/",
ResourceRootPath: "/storage/volume",
@ -30,12 +32,16 @@ func (c *ComputeClient) StorageVolumes() *StorageVolumeClient {
}
// StorageVolumeKind defines the kinds of storage volumes that can be managed
type StorageVolumeKind string
const (
// StorageVolumeKindDefault - "/oracle/public/storage/default"
StorageVolumeKindDefault StorageVolumeKind = "/oracle/public/storage/default"
// StorageVolumeKindLatency - "/oracle/public/storage/latency"
StorageVolumeKindLatency StorageVolumeKind = "/oracle/public/storage/latency"
StorageVolumeKindSSD StorageVolumeKind = "/oracle/public/storage/ssd/gpl"
// StorageVolumeKindSSD - "/oracle/public/storage/ssd/gpl"
StorageVolumeKindSSD StorageVolumeKind = "/oracle/public/storage/ssd/gpl"
)
// StorageVolumeInfo represents information retrieved from the service about a Storage Volume.
@ -43,30 +49,23 @@ 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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// The OS platform this volume is compatible with.
Platform string `json:"platform,omitempty"`
@ -74,9 +73,6 @@ type StorageVolumeInfo struct {
// 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"`
@ -107,6 +103,19 @@ type StorageVolumeInfo struct {
// Uniform Resource Identifier
URI string `json:"uri,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"`
// All volumes are managed volumes. Default value is true.
Managed bool `json:"managed,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"`
// Specific imagelist entry version to extract.
ImageListEntry int `json:"imagelist_entry,omitempty"`
}
func (c *StorageVolumeClient) getStorageVolumePath(name string) string {
@ -149,6 +158,9 @@ type CreateStorageVolumeInput struct {
// Comma-separated strings that tag the storage volume.
Tags []string `json:"tags,omitempty"`
// Timeout to wait polling storage volume status.
PollInterval time.Duration `json:"-"`
// Timeout to wait for storage volume creation.
Timeout time.Duration `json:"-"`
}
@ -165,23 +177,26 @@ func (c *StorageVolumeClient) CreateStorageVolume(input *CreateStorageVolumeInpu
input.Size = sizeInBytes
var storageInfo StorageVolumeInfo
if err := c.createResource(&input, &storageInfo); err != nil {
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.PollInterval == 0 {
input.PollInterval = waitForVolumeReadyPollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForVolumeReadyTimeout
input.Timeout = waitForVolumeReadyTimeout
}
volume, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.Timeout)
volume, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.PollInterval, input.Timeout)
if err != nil {
if volume != nil {
deleteInput := &DeleteStorageVolumeInput{
Name: volume.Name,
}
if err := c.DeleteStorageVolume(deleteInput); err != nil {
if err = c.DeleteStorageVolume(deleteInput); err != nil {
return nil, err
}
}
@ -194,6 +209,9 @@ type DeleteStorageVolumeInput struct {
// The three-part name of the object (/Compute-identity_domain/user/object).
Name string `json:"name"`
// Timeout to wait betweeon polling storage volume status
PollInterval time.Duration `json:"-"`
// Timeout to wait for storage volume deletion
Timeout time.Duration `json:"-"`
}
@ -205,11 +223,14 @@ func (c *StorageVolumeClient) DeleteStorageVolume(input *DeleteStorageVolumeInpu
}
// Should never be nil, but protect against it anyways
if input.PollInterval == 0 {
input.PollInterval = waitForVolumeDeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForVolumeDeleteTimeout
input.Timeout = waitForVolumeDeleteTimeout
}
return c.waitForStorageVolumeToBeDeleted(input.Name, input.Timeout)
return c.waitForStorageVolumeToBeDeleted(input.Name, input.PollInterval, input.Timeout)
}
// GetStorageVolumeInput represents the body of an API request to obtain a Storage Volume.
@ -220,7 +241,7 @@ type GetStorageVolumeInput struct {
func (c *StorageVolumeClient) success(result *StorageVolumeInfo) (*StorageVolumeInfo, error) {
c.unqualify(&result.ImageList)
c.unqualify(&result.Name)
result.Name = c.getUnqualifiedName(result.FQDN)
c.unqualify(&result.Snapshot)
sizeInMegaBytes, err := sizeInGigaBytes(result.Size)
@ -278,6 +299,9 @@ type UpdateStorageVolumeInput struct {
// Comma-separated strings that tag the storage volume.
Tags []string `json:"tags,omitempty"`
// Time to wait between polling storage volume status
PollInterval time.Duration `json:"-"`
// Time to wait for storage volume ready
Timeout time.Duration `json:"-"`
}
@ -299,11 +323,14 @@ func (c *StorageVolumeClient) UpdateStorageVolume(input *UpdateStorageVolumeInpu
return nil, err
}
if input.PollInterval == 0 {
input.PollInterval = waitForVolumeReadyPollInterval
}
if input.Timeout == 0 {
input.Timeout = WaitForVolumeReadyTimeout
input.Timeout = waitForVolumeReadyTimeout
}
volumeInfo, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.Timeout)
volumeInfo, err := c.waitForStorageVolumeToBecomeAvailable(input.Name, input.PollInterval, input.Timeout)
if err != nil {
return nil, err
}
@ -312,11 +339,12 @@ func (c *StorageVolumeClient) UpdateStorageVolume(input *UpdateStorageVolumeInpu
}
// 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) {
func (c *StorageVolumeClient) waitForStorageVolumeToBecomeAvailable(name string, pollInterval, timeout time.Duration) (*StorageVolumeInfo, error) {
var waitResult *StorageVolumeInfo
err := c.client.WaitFor(
fmt.Sprintf("storage volume %s to become available", c.getQualifiedName(name)),
pollInterval,
timeout,
func() (bool, error) {
getRequest := &GetStorageVolumeInput{
@ -345,9 +373,10 @@ func (c *StorageVolumeClient) waitForStorageVolumeToBecomeAvailable(name string,
}
// waitForStorageVolumeToBeDeleted waits until the specified storage volume has been deleted.
func (c *StorageVolumeClient) waitForStorageVolumeToBeDeleted(name string, timeout time.Duration) error {
func (c *StorageVolumeClient) waitForStorageVolumeToBeDeleted(name string, pollInterval, timeout time.Duration) error {
return c.client.WaitFor(
fmt.Sprintf("storage volume %s to be deleted", c.getQualifiedName(name)),
pollInterval,
timeout,
func() (bool, error) {
getRequest := &GetStorageVolumeInput{

View File

@ -34,7 +34,7 @@ func newAuthenticatingServer(handler func(w http.ResponseWriter, r *http.Request
}))
}
func getTestClient(c *opc.Config) (*ComputeClient, error) {
func getTestClient(c *opc.Config) (*Client, error) {
// Build up config with default values if omitted
if c.APIEndpoint == nil {
if os.Getenv("OPC_ENDPOINT") == "" {
@ -73,7 +73,8 @@ func getTestClient(c *opc.Config) (*ComputeClient, error) {
return NewComputeClient(c)
}
func getBlankTestClient() (*ComputeClient, *httptest.Server, error) {
// nolint: deadcode
func getBlankTestClient() (*Client, *httptest.Server, error) {
server := newAuthenticatingServer(func(w http.ResponseWriter, r *http.Request) {
})
@ -96,23 +97,26 @@ func getBlankTestClient() (*ComputeClient, *httptest.Server, error) {
}
// 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"
// nolint: deadcode
func getStubClient(endpoint *url.URL) (*Client, error) {
testAttr := "test"
config := &opc.Config{
IdentityDomain: &domain,
Username: &username,
Password: &password,
IdentityDomain: &testAttr,
Username: &testAttr,
Password: &testAttr,
APIEndpoint: endpoint,
}
return getTestClient(config)
}
// nolint: deadcode
func unmarshalRequestBody(t *testing.T, r *http.Request, target interface{}) {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
err := json.Unmarshal(buf.Bytes(), target)
_, err := buf.ReadFrom(r.Body)
if err != nil {
t.Fatalf("Error reading buffer: %s", err)
}
err = json.Unmarshal(buf.Bytes(), target)
if err != nil {
t.Fatalf("Error marshalling request: %s", err)
}

View File

@ -1,13 +1,15 @@
package compute
// VirtNICsClient defines a vritual nics client
type VirtNICsClient struct {
ResourceClient
}
func (c *ComputeClient) VirtNICs() *VirtNICsClient {
// VirtNICs returns a virtual nics client
func (c *Client) VirtNICs() *VirtNICsClient {
return &VirtNICsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "Virtual NIC",
ContainerPath: "/network/v1/vnic/",
ResourceRootPath: "/network/v1/vnic",
@ -15,28 +17,32 @@ func (c *ComputeClient) VirtNICs() *VirtNICsClient {
}
}
// VirtualNIC defines the attributes in a virtual nic
type VirtualNIC struct {
// Description of the object.
Description string `json:"description"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// 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"`
Name string
// 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"`
URI string `json:"uri"`
}
// Can only GET a virtual NIC, not update, create, or delete
// GetVirtualNICInput 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"`
}
// GetVirtualNIC returns the specified virtual nic
func (c *VirtNICsClient) GetVirtualNIC(input *GetVirtualNICInput) (*VirtualNIC, error) {
var virtNIC VirtualNIC
input.Name = c.getQualifiedName(input.Name)
@ -47,6 +53,6 @@ func (c *VirtNICsClient) GetVirtualNIC(input *GetVirtualNICInput) (*VirtualNIC,
}
func (c *VirtNICsClient) success(info *VirtualNIC) (*VirtualNIC, error) {
c.unqualify(&info.Name)
info.Name = c.getUnqualifiedName(info.FQDN)
return info, nil
}

View File

@ -1,13 +1,15 @@
package compute
// VirtNICSetsClient defines a virtual set nic client
type VirtNICSetsClient struct {
ResourceClient
}
func (c *ComputeClient) VirtNICSets() *VirtNICSetsClient {
// VirtNICSets returns a virtual nic sets client
func (c *Client) VirtNICSets() *VirtNICSetsClient {
return &VirtNICSetsClient{
ResourceClient: ResourceClient{
ComputeClient: c,
Client: c,
ResourceDescription: "Virtual NIC Set",
ContainerPath: "/network/v1/vnicset/",
ResourceRootPath: "/network/v1/vnicset",
@ -15,22 +17,25 @@ func (c *ComputeClient) VirtNICSets() *VirtNICSetsClient {
}
}
// Describes an existing virtual nic set
// VirtualNICSet 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"`
// Fully Qualified Domain Name
FQDN string `json:"name"`
// Name of the VNIC set.
Name string `json:"name"`
Name string
// 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"`
URI string `json:"uri"`
// List of VNICs associated with this VNIC set.
VirtualNICs []string `json:"vnics"`
}
// CreateVirtualNICSetInput specifies the details of the virutal nic set to create
type CreateVirtualNICSetInput struct {
// List of ACLs applied to the VNICs in the set.
// Optional
@ -50,6 +55,7 @@ type CreateVirtualNICSetInput struct {
VirtualNICs []string `json:"vnics"`
}
// CreateVirtualNICSet creates a new virtual nic set
func (c *VirtNICSetsClient) CreateVirtualNICSet(input *CreateVirtualNICSetInput) (*VirtualNICSet, error) {
input.Name = c.getQualifiedName(input.Name)
input.AppliedACLs = c.getQualifiedAcls(input.AppliedACLs)
@ -66,12 +72,14 @@ func (c *VirtNICSetsClient) CreateVirtualNICSet(input *CreateVirtualNICSetInput)
return c.success(&virtNicSet)
}
// GetVirtualNICSetInput specifies which virutal nic to obtain
type GetVirtualNICSetInput struct {
// The three-part name (/Compute-identity_domain/user/object) of the virtual NIC set.
// Required
Name string `json:"name"`
}
// GetVirtualNICSet retrieves the specified virtual nic set
func (c *VirtNICSetsClient) GetVirtualNICSet(input *GetVirtualNICSetInput) (*VirtualNICSet, error) {
var virtNicSet VirtualNICSet
// Qualify Name
@ -83,6 +91,7 @@ func (c *VirtNICSetsClient) GetVirtualNICSet(input *GetVirtualNICSetInput) (*Vir
return c.success(&virtNicSet)
}
// UpdateVirtualNICSetInput specifies the information that will be updated in the virtual nic set
type UpdateVirtualNICSetInput struct {
// List of ACLs applied to the VNICs in the set.
// Optional
@ -102,6 +111,7 @@ type UpdateVirtualNICSetInput struct {
VirtualNICs []string `json:"vnics"`
}
// UpdateVirtualNICSet updates the specified virtual nic set
func (c *VirtNICSetsClient) UpdateVirtualNICSet(input *UpdateVirtualNICSetInput) (*VirtualNICSet, error) {
input.Name = c.getQualifiedName(input.Name)
input.AppliedACLs = c.getQualifiedAcls(input.AppliedACLs)
@ -119,12 +129,14 @@ func (c *VirtNICSetsClient) UpdateVirtualNICSet(input *UpdateVirtualNICSetInput)
return c.success(&virtNICSet)
}
// DeleteVirtualNICSetInput specifies the virtual nic set to delete
type DeleteVirtualNICSetInput struct {
// The name of the virtual NIC set.
// Required
Name string `json:"name"`
}
// DeleteVirtualNICSet deletes the specified virtual nic set
func (c *VirtNICSetsClient) DeleteVirtualNICSet(input *DeleteVirtualNICSetInput) error {
input.Name = c.getQualifiedName(input.Name)
return c.deleteResource(input.Name)
@ -147,7 +159,7 @@ func (c *VirtNICSetsClient) unqualifyAcls(acls []string) []string {
}
func (c *VirtNICSetsClient) success(info *VirtualNICSet) (*VirtualNICSet, error) {
c.unqualify(&info.Name)
info.Name = c.getUnqualifiedName(info.FQDN)
info.AppliedACLs = c.unqualifyAcls(info.AppliedACLs)
info.VirtualNICs = c.getUnqualifiedList(info.VirtualNICs)
return info, nil

View File

@ -0,0 +1,451 @@
package compute
import (
"fmt"
"time"
"github.com/hashicorp/go-oracle-terraform/client"
)
const (
vpnEndpointV2Description = "vpn endpoint v2"
vpnEndpointV2ContainerPath = "/vpnendpoint/v2/"
vpnEndpointV2ResourcePath = "/vpnendpoint/v2"
waitForVPNEndpointV2ActivePollInterval = 10 * time.Second
waitForVPNEndpointV2ActiveTimeout = 3600 * time.Second
waitForVPNEndpointV2DeletePollInterval = 10 * time.Second
waitForVPNEndpointV2DeleteTimeout = 3600 * time.Second
)
// VPNEndpointV2sClient returns a VPNEndpointV2 client
type VPNEndpointV2sClient struct {
ResourceClient
}
// VPNEndpointV2s returns an VPNEndpointV2sClient that can be used to access the
// necessary CRUD functions for VPN Endpoint V2s.
func (c *Client) VPNEndpointV2s() *VPNEndpointV2sClient {
return &VPNEndpointV2sClient{
ResourceClient: ResourceClient{
Client: c,
ResourceDescription: vpnEndpointV2Description,
ContainerPath: vpnEndpointV2ContainerPath,
ResourceRootPath: vpnEndpointV2ResourcePath,
},
}
}
// VPNEndpointTunnelStatus defines the different statuses a VPN Endpoint tunnel can be in
type VPNEndpointTunnelStatus string
const (
// VPNEndpointTunnelStatusPending - the tunnel is in a pending state
VPNEndpointTunnelStatusPending VPNEndpointTunnelStatus = "PENDING"
// VPNEndpointTunnelStatusUp - the tunnel is in a up state
VPNEndpointTunnelStatusUp VPNEndpointTunnelStatus = "UP"
// VPNEndpointTunnelStatusDown - the tunnel is in a down state
VPNEndpointTunnelStatusDown VPNEndpointTunnelStatus = "DOWN"
// VPNEndpointTunnelStatusError - the tunnel is in a error state
VPNEndpointTunnelStatusError VPNEndpointTunnelStatus = "ERROR"
)
// VPNEndpointLifeCycleState defines the different lifecycle states a VPN Endpoint can be in
type VPNEndpointLifeCycleState string
const (
// VPNEndpointLifeCycleStateProvisioning - the endpoint is in a provisioning state
VPNEndpointLifeCycleStateProvisioning VPNEndpointLifeCycleState = "provisioning"
// VPNEndpointLifeCycleStateReady - the endpoint is in a ready state
VPNEndpointLifeCycleStateReady VPNEndpointLifeCycleState = "ready"
// VPNEndpointLifeCycleStateDeleting - the endpoint is in a ready state
VPNEndpointLifeCycleStateDeleting VPNEndpointLifeCycleState = "deleting"
// VPNEndpointLifeCycleStateError - the endpoint is in a error state
VPNEndpointLifeCycleStateError VPNEndpointLifeCycleState = "error"
// VPNEndpointLifeCycleStateUpdating - the endpoint is in a updating state
VPNEndpointLifeCycleStateUpdating VPNEndpointLifeCycleState = "updating"
)
// VPNEndpointV2Info contains the exported fields necessary to hold all the information about an
// VPN Endpoint V2
type VPNEndpointV2Info struct {
// IP address of the VPN gateway in your data center through which you want
// to connect to the Oracle Cloud VPN gateway.
CustomerVPNGateway string `json:"customer_vpn_gateway"`
// Whether the tunnel is enabled or disabled
// Optional
Enabled bool `json:"enabled"`
// The Internet Key Exchange (IKE) ID that you have specified. The default
// value is the public IP address of the cloud gateway.
IKEIdentifier string `json:"ikeIdentifier"`
// The name of the IP network on which the cloud gateway is created by VPNaaS.
IPNetwork string `json:"ipNetwork"`
// The name of the VPN Endpoint V2
Name string `json:"name"`
// The lifecycle state the VPNEndpointV2 is in
LifeCycleState VPNEndpointLifeCycleState `json:"lifecycleState"`
// Indicates whether Perfect Forward Secrecy (PFS) is required and your third-party device supports PFS.
PFSFlag bool `json:"pfsFlag"`
// Settings for Phase 1 of protocol (IKE).
Phase1Settings Phase1Settings `json:"phase1Settings"`
// Settings for Phase 2 of protocol (IPSEC).
Phase2Settings Phase2Settings `json:"phase2Settings"`
// The pre-shared VPN key.
PSK string `json:"psk"`
// List of routes (CIDR prefixes) that are reachable through this VPN tunnel.
ReachableRoutes []string `json:"reachable_routes"`
// Current status of the tunnel. The tunnel can be in one of the following states:
// PENDING: indicates that your VPN connection is being set up.
// UP: indicates that your VPN connection is established.
// DOWN: indicates that your VPN connection is down.
// ERROR: indicates that your VPN connection is in the error state.
TunnelStatus VPNEndpointTunnelStatus `json:"tunnelStatus"`
// Uniform Resource Identifier for the VPN Endpoint V2
URI string `json:"uri"`
// Comma-separated list of vNIC sets. Traffic is allowed to and
// from these vNIC sets to the cloud gateway's vNIC set.
VNICSets []string `json:"vnicSets"`
}
// Phase1Settings define the attributes related to Phase 1 Protocol (IKE)
type Phase1Settings struct {
// Encryption options for IKE. Permissible values are aes128, aes192, aes256.
Encryption string `json:"encryption"`
// Authentication options for IKE. Permissible values are sha1, sha2_256, and md5.
Hash string `json:"hash"`
// Diffie-Hellman group for both IKE and ESP. It is applicable for ESP only if PFS is enabled.
// Permissible values are group5, group14, group22, group23, and group24.
DHGroup string `json:"dhGroup"`
}
// Phase2Settings define the attributes related to Phase 2 Protocol (IPSEC)
type Phase2Settings struct {
// Encryption options for IKE. Permissible values are aes128, aes192, aes256.
Encryption string `json:"encryption"`
// Authentication options for IKE. Permissible values are sha1, sha2_256, and md5.
Hash string `json:"hash"`
}
// CreateVPNEndpointV2Input define the attributes related to creating a vpn endpoint v2
type CreateVPNEndpointV2Input struct {
// Specify the IP address of the VPN gateway in your data center through which you want
// to connect to the Oracle Cloud VPN gateway. Your gateway device must support route-based
// VPN and IKE (Internet Key Exchange) configuration using pre-shared keys.
// Required
CustomerVPNGateway string `json:"customer_vpn_gateway"`
// Description of the VPN Endpoint
Description string `json:"description,omitempty"`
// Enable/Disable the tunnel
// Optional
Enabled bool `json:"enabled,omitempty"`
// The Internet Key Exchange (IKE) ID. If you don't specify a value, the default value is
// the public IP address of the cloud gateway. You can specify either an alternative IP address,
// or any text string that you want to use as the IKE ID. If you specify a text string, you must
// prefix the string with @. For example, if you want to specify the text IKEID-for-VPN1, specify
// @IKEID-for-VPN1 as the value in request body. If you specify an IP address, don't prefix it with @.
// The IKE ID is case sensitive and can contain a maximum of 255 ASCII alphanumeric characters
// including special characters, period (.), hyphen (-), and underscore (_). The IKE ID can't contain
// embedded space characters.
// Note: If you specify the IKE ID, ensure that you specify the Peer ID type as Domain Name on the
// third-party device in your data center. Other Peer ID types, such as email address, firewall
// identifier or key identifier, aren't supported.
// Optional
IKEIdentifier string `json:"ikeIdentifier,omitempty"`
// Specify the name of the IP network
// which you want to create the cloud gateway. When you send a request to create a VPN connection,
// a cloud gateway is created and this is assigned an available IP address from the IP network that
// you specify. So, the cloud gateway is directly connected to the IP network that you specify.
// You can only specify a single IP network. All other IP networks with are connected to the
// specified IP network through an IP network exchange are discovered and added automatically to
// the VPN connection.
// Required
IPNetwork string `json:"ipNetwork"`
// The name of the VPN Endpoint V2 to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// This is enabled (set to true) by default. If your third-party device supports Perfect Forward
// Secrecy (PFS), set this parameter to true to require PFS.
// Optional. Default true
PFSFlag bool `json:"pfsFlag,omitmepty"`
// Settings for Phase 1 of protocol (IKE).
// Optional
Phase1Settings *Phase1Settings `json:"phase1Settings,omitempty"`
// Settings for Phase 2 of protocol (IPSEC).
// Optional
Phase2Settings *Phase2Settings `json:"phase2Settings,omitempty"`
// Pre-shared VPN key. This secret key is shared between your network gateway and
// the Oracle Cloud network for authentication. Specify the full path and name of
// the text file that contains the pre-shared key. Ensure that the permission level
// of the text file is set to 400. The pre-shared VPN key must not exceed 256 characters.
// Required
PSK string `json:"psk"`
// Specify a list of routes (CIDR prefixes) that are reachable through this VPN tunnel.
// You can specify a maximum of 20 IP subnet addresses. Specify IPv4 addresses in dot-decimal
// notation with or without mask.
// Required
ReachableRoutes []string `json:"reachable_routes"`
// An array of tags
Tags []string `json:"tags"`
// Comma-separated list of vNIC sets. Traffic is allowed to and from these vNIC sets to the
// cloud gateway's vNIC set.
// Required
VNICSets []string `json:"vnicSets"`
// Time to wait between polls to check status
PollInterval time.Duration `json:"-"`
// Time to wait for an vpn endoint v2 to be ready
Timeout time.Duration `json:"-"`
}
// CreateVPNEndpointV2 creates a new VPN Endpoint V2 from an VPNEndpointV2sClient and an input struct.
// Returns a populated Info struct for the VPN Endpoint V2, and any errors
func (c *VPNEndpointV2sClient) CreateVPNEndpointV2(input *CreateVPNEndpointV2Input) (*VPNEndpointV2Info, error) {
input.Name = c.getQualifiedName(input.Name)
input.IPNetwork = c.getQualifiedName(input.IPNetwork)
input.VNICSets = c.getQualifiedList(input.VNICSets)
var createdVPNEndpointV2Info VPNEndpointV2Info
if err := c.createResource(&input, &createdVPNEndpointV2Info); err != nil {
return nil, err
}
// Call wait for vpn endpoint ready now, as creating the vpn endpoint v2 takes time
getInput := &GetVPNEndpointV2Input{
Name: input.Name,
}
if input.PollInterval == 0 {
input.PollInterval = waitForVPNEndpointV2ActivePollInterval
}
if input.Timeout == 0 {
input.Timeout = waitForVPNEndpointV2ActiveTimeout
}
// Wait for vpn endpoint v2 to be ready and return the result
vpnEndpointV2Info, vpnEndpointV2InfoError := c.WaitForVPNEndpointV2Ready(getInput, input.PollInterval, input.Timeout)
if vpnEndpointV2InfoError != nil {
return nil, fmt.Errorf("Error creating VPNEndpointV2 %q: %s", getInput.Name, vpnEndpointV2InfoError)
}
return vpnEndpointV2Info, nil
}
// GetVPNEndpointV2Input specifies the information needed to retrive a VPNEndpointV2
type GetVPNEndpointV2Input struct {
// The name of the VPN Endpoint V2 to query for. Case-sensitive
// Required
Name string `json:"name"`
}
// GetVPNEndpointV2 returns a populated VPNEndpointV2Info struct from an input struct
func (c *VPNEndpointV2sClient) GetVPNEndpointV2(input *GetVPNEndpointV2Input) (*VPNEndpointV2Info, error) {
input.Name = c.getQualifiedName(input.Name)
var ipInfo VPNEndpointV2Info
if err := c.getResource(input.Name, &ipInfo); err != nil {
return nil, err
}
return c.success(&ipInfo)
}
// UpdateVPNEndpointV2Input defines what to update in a VPN Endpoint V2
// Only PSK and ReachableRoutes are updatable
type UpdateVPNEndpointV2Input struct {
// Specify the IP address of the VPN gateway in your data center through which you want
// to connect to the Oracle Cloud VPN gateway. Your gateway device must support route-based
// VPN and IKE (Internet Key Exchange) configuration using pre-shared keys.
// Required
CustomerVPNGateway string `json:"customer_vpn_gateway"`
// Description of the VPNGatewayV2
Description string `json:"description,omitempty"`
// Enable/Disable the tunnel
// Optional
Enabled bool `json:"enabled,omitempty"`
// The Internet Key Exchange (IKE) ID. If you don't specify a value, the default value is
// the public IP address of the cloud gateway. You can specify either an alternative IP address,
// or any text string that you want to use as the IKE ID. If you specify a text string, you must
// prefix the string with @. For example, if you want to specify the text IKEID-for-VPN1, specify
// @IKEID-for-VPN1 as the value in request body. If you specify an IP address, don't prefix it with @.
// The IKE ID is case sensitive and can contain a maximum of 255 ASCII alphanumeric characters
// including special characters, period (.), hyphen (-), and underscore (_). The IKE ID can't contain
// embedded space characters.
// Note: If you specify the IKE ID, ensure that you specify the Peer ID type as Domain Name on the
// third-party device in your data center. Other Peer ID types, such as email address, firewall
// identifier or key identifier, aren't supported.
// Optional
IKEIdentifier string `json:"ikeIdentifier,omitempty"`
// Specify the name of the IP network
// which you want to create the cloud gateway. When you send a request to create a VPN connection,
// a cloud gateway is created and this is assigned an available IP address from the IP network that
// you specify. So, the cloud gateway is directly connected to the IP network that you specify.
// You can only specify a single IP network. All other IP networks with are connected to the
// specified IP network through an IP network exchange are discovered and added automatically to
// the VPN connection.
// Required
IPNetwork string `json:"ipNetwork"`
// The name of the VPN Endpoint V2 to create. Object names can only contain alphanumeric,
// underscore, dash, and period characters. Names are case-sensitive.
// Required
Name string `json:"name"`
// This is enabled (set to true) by default. If your third-party device supports Perfect Forward
// Secrecy (PFS), set this parameter to true to require PFS.
// Optional. Default true
PFSFlag bool `json:"pfsFlag,omitempty"`
// Settings for Phase 1 of protocol (IKE).
// Optional
Phase1Settings *Phase1Settings `json:"phase1Settings,omitempty"`
// Settings for Phase 2 of protocol (IPSEC).
// Optional
Phase2Settings *Phase2Settings `json:"phase2Settings,omitempty"`
// Pre-shared VPN key. This secret key is shared between your network gateway and
// the Oracle Cloud network for authentication. Specify the full path and name of
// the text file that contains the pre-shared key. Ensure that the permission level
// of the text file is set to 400. The pre-shared VPN key must not exceed 256 characters.
// Required.
PSK string `json:"psk"`
// Specify a list of routes (CIDR prefixes) that are reachable through this VPN tunnel.
// You can specify a maximum of 20 IP subnet addresses. Specify IPv4 addresses in dot-decimal
// notation with or without mask.
// Required
ReachableRoutes []string `json:"reachable_routes"`
// Array of tags
Tags []string `json:"tags,omitempty"`
// Comma-separated list of vNIC sets. Traffic is allowed to and from these vNIC sets to the
// cloud gateway's vNIC set.
// Required
VNICSets []string `json:"vnicSets"`
// Time to wait between polls to check status
PollInterval time.Duration `json:"-"`
// Time to wait for an vpn endoint v2 to be ready
Timeout time.Duration `json:"-"`
}
// UpdateVPNEndpointV2 update the VPN Endpoint V2
func (c *VPNEndpointV2sClient) UpdateVPNEndpointV2(updateInput *UpdateVPNEndpointV2Input) (*VPNEndpointV2Info, error) {
updateInput.Name = c.getQualifiedName(updateInput.Name)
updateInput.IPNetwork = c.getQualifiedName(updateInput.IPNetwork)
updateInput.VNICSets = c.getQualifiedList(updateInput.VNICSets)
var ipInfo VPNEndpointV2Info
if err := c.updateResource(updateInput.Name, updateInput, &ipInfo); err != nil {
return nil, err
}
// Call wait for vpn endpoint ready now, as creating the vpn endpoint v2 takes time
getInput := &GetVPNEndpointV2Input{
Name: updateInput.Name,
}
if updateInput.PollInterval == 0 {
updateInput.PollInterval = waitForVPNEndpointV2ActivePollInterval
}
if updateInput.Timeout == 0 {
updateInput.Timeout = waitForVPNEndpointV2ActiveTimeout
}
// Wait for vpn endpoint v2 to be ready and return the result
vpnEndpointV2Info, vpnEndpointV2InfoError := c.WaitForVPNEndpointV2Ready(getInput, updateInput.PollInterval, updateInput.Timeout)
if vpnEndpointV2InfoError != nil {
return nil, fmt.Errorf("Error creating VPNEndpointV2 %q: %s", getInput.Name, vpnEndpointV2InfoError)
}
return vpnEndpointV2Info, nil
}
// DeleteVPNEndpointV2Input defines the attributes required for deleting a vpn endpoint v2
type DeleteVPNEndpointV2Input struct {
// The name of the VPN Endpoint V2 to query for. Case-sensitive
// Required
Name string `json:"name"`
// Poll Interval for delete request
PollInterval time.Duration `json:"-"`
// Timeout for delete request
Timeout time.Duration `json:"-"`
}
// DeleteVPNEndpointV2 deletes the specified vpn endpoint v2
func (c *VPNEndpointV2sClient) DeleteVPNEndpointV2(input *DeleteVPNEndpointV2Input) error {
if err := c.deleteResource(input.Name); err != nil {
return err
}
if input.PollInterval == 0 {
input.PollInterval = waitForVPNEndpointV2DeletePollInterval
}
if input.Timeout == 0 {
input.Timeout = waitForVPNEndpointV2DeleteTimeout
}
return c.WaitForVPNEndpointV2Deleted(input, input.PollInterval, input.Timeout)
}
// Unqualifies any qualified fields in the VPNEndpointV2Info struct
func (c *VPNEndpointV2sClient) success(info *VPNEndpointV2Info) (*VPNEndpointV2Info, error) {
c.unqualify(&info.Name)
c.unqualify(&info.IPNetwork)
info.VNICSets = c.getUnqualifiedList(info.VNICSets)
return info, nil
}
// WaitForVPNEndpointV2Ready waits for an vpn endpoint to be in an up or down state
func (c *VPNEndpointV2sClient) WaitForVPNEndpointV2Ready(input *GetVPNEndpointV2Input, pollInterval, timeout time.Duration) (*VPNEndpointV2Info, error) {
var info *VPNEndpointV2Info
var getErr error
err := c.client.WaitFor("vpn endpoint to be ready", pollInterval, timeout, func() (bool, error) {
info, getErr = c.GetVPNEndpointV2(input)
if getErr != nil {
return false, getErr
}
c.client.DebugLogString(fmt.Sprintf("VPNEndpointV2 name is %q, VPNEndpointV2 info is %+v", info.Name, info))
switch s := info.LifeCycleState; s {
case VPNEndpointLifeCycleStateProvisioning:
return false, nil
case VPNEndpointLifeCycleStateUpdating:
return false, nil
case VPNEndpointLifeCycleStateReady:
c.client.DebugLogString(fmt.Sprintf("VPNEndpointV2 %s", info.LifeCycleState))
return true, nil
case VPNEndpointLifeCycleStateError:
return false, fmt.Errorf("Error waiting for VPNEndpointV2 %q to be ready", info.Name)
case VPNEndpointLifeCycleStateDeleting:
return false, fmt.Errorf("Error waiting for VPNEndpointV2 %q to be ready", info.Name)
default:
return false, fmt.Errorf("Unknown VPNEndpointV2 lifecycle state: %s, erroring", s)
}
})
return info, err
}
// WaitForVPNEndpointV2Deleted waits for an VPNEndpointV2to be fully deleted.
func (c *VPNEndpointV2sClient) WaitForVPNEndpointV2Deleted(input *DeleteVPNEndpointV2Input, pollInterval, timeout time.Duration) error {
return c.client.WaitFor("VPNEndpointV2 to be deleted", pollInterval, timeout, func() (bool, error) {
var info VPNEndpointV2Info
if err := c.getResource(input.Name, &info); err != nil {
if client.WasNotFoundError(err) {
// VPNEndpointV2 could not be found, thus deleted
return true, nil
}
// Some other error occurred trying to get VPNEndpointV2, exit
return false, err
}
switch s := info.LifeCycleState; s {
case VPNEndpointLifeCycleStateProvisioning:
return false, fmt.Errorf("Error deleting VPNEndpointV2: %+v", info)
case VPNEndpointLifeCycleStateDeleting:
c.client.DebugLogString("VPNEndpointV2 deleting")
return false, nil
case VPNEndpointLifeCycleStateReady:
c.client.DebugLogString("VPNEndpointV2 deleting")
return false, nil
case VPNEndpointLifeCycleStateUpdating:
c.client.DebugLogString("VPNEndpointV2 updating")
return false, nil
case VPNEndpointLifeCycleStateError:
c.client.DebugLogString("VPNEndpointV2 deleting")
return false, nil
default:
return false, fmt.Errorf("Unknown VPNEndpointV2 lifecycle state: %s, erroring", s)
}
})
}

View File

@ -5,6 +5,7 @@ import (
"net/url"
)
// Config details the parameters needed to authenticate with Oracle Clouds API
type Config struct {
Username *string
Password *string
@ -17,6 +18,7 @@ type Config struct {
UserAgent *string
}
// NewConfig returns a blank config to populate with the neccessary fields to authenitcate with Oracle's API
func NewConfig() *Config {
return &Config{}
}

View File

@ -1,9 +1,11 @@
package opc
// String returns a pointer to a string
func String(v string) *string {
return &v
}
// Int returns a pointer to an int
func Int(v int) *int {
return &v
}

View File

@ -2,6 +2,7 @@ package opc
import "fmt"
// OracleError details the parameters of an error returned from Oracle's API
type OracleError struct {
StatusCode int
Message string

View File

@ -8,10 +8,13 @@ import (
)
const (
LogOff LogLevelType = 0
// LogOff turns logging off
LogOff LogLevelType = 0
// LogDebug turns logging to debug
LogDebug LogLevelType = 1
)
// LogLevelType details the constants that log level can be in
type LogLevelType uint
// Logger interface. Should be satisfied by Terraform's logger as well as the Default logger
@ -19,13 +22,15 @@ type Logger interface {
Log(...interface{})
}
// LoggerFunc details the logger functions
type LoggerFunc func(...interface{})
// Log logs the specified messages
func (f LoggerFunc) Log(args ...interface{}) {
f(args...)
}
// Returns a default logger if one isn't specified during configuration
// NewDefaultLogger returns a default logger if one isn't specified during configuration
func NewDefaultLogger() Logger {
logWriter, err := LogOutput()
if err != nil {
@ -45,6 +50,7 @@ func (l defaultLogger) Log(args ...interface{}) {
l.logger.Println(args...)
}
// LogOutput outputs the requested messages
func LogOutput() (logOutput io.Writer, err error) {
// Default to nil
logOutput = ioutil.Discard
@ -59,12 +65,11 @@ func LogOutput() (logOutput io.Writer, err error) {
return
}
// Gets current Log Level from the ORACLE_LOG env var
// LogLevel 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
}
return LogDebug
}

18
vendor/vendor.json vendored
View File

@ -1020,22 +1020,22 @@
"revision": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"
},
{
"checksumSHA1": "hjQfXn32Tvuu6IJACOTsMzm+AbA=",
"checksumSHA1": "2HXZQWsVNPQme21DBmz9P3n9NNc=",
"path": "github.com/hashicorp/go-oracle-terraform/client",
"revision": "62e2241f9c4154d5603a3678adc912991a47a468",
"revisionTime": "2018-01-31T23:42:02Z"
"revision": "007121241b797759456e4cdcb8ae98f431fdb7e0",
"revisionTime": "2018-10-15T20:29:09Z"
},
{
"checksumSHA1": "yoA7SyeQNJ8XxwC7IcXdJ2kOTqg=",
"checksumSHA1": "+7uE289ixv+xwEk99EiXKecZt5k=",
"path": "github.com/hashicorp/go-oracle-terraform/compute",
"revision": "62e2241f9c4154d5603a3678adc912991a47a468",
"revisionTime": "2018-01-31T23:42:02Z"
"revision": "007121241b797759456e4cdcb8ae98f431fdb7e0",
"revisionTime": "2018-10-15T20:29:09Z"
},
{
"checksumSHA1": "NuObCk0/ybL3w++EnltgrB1GQRc=",
"checksumSHA1": "aeXObRk6gAfuvnT+puKaEib7dm0=",
"path": "github.com/hashicorp/go-oracle-terraform/opc",
"revision": "62e2241f9c4154d5603a3678adc912991a47a468",
"revisionTime": "2018-01-31T23:42:02Z"
"revision": "007121241b797759456e4cdcb8ae98f431fdb7e0",
"revisionTime": "2018-10-15T20:29:09Z"
},
{
"checksumSHA1": "/yKfFSspjuDzyOe/bBslrPzyfYM=",