Merge pull request #6142 from harveylowndes/use-official-go-sdk

builder/oracle: Use official OCI Go SDK
This commit is contained in:
M. Marsh 2018-04-24 16:34:38 -07:00 committed by GitHub
commit 148f7d39e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
595 changed files with 40030 additions and 2092 deletions

View File

@ -3,12 +3,12 @@ package oci
import (
"fmt"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
"github.com/oracle/oci-go-sdk/core"
)
// Artifact is an artifact implementation that contains a built Custom Image.
type Artifact struct {
Image client.Image
Image core.Image
Region string
driver Driver
}
@ -26,13 +26,18 @@ func (a *Artifact) Files() []string {
// Id returns the OCID of the associated Image.
func (a *Artifact) Id() string {
return a.Image.ID
return *a.Image.Id
}
func (a *Artifact) String() string {
var displayName string
if a.Image.DisplayName != nil {
displayName = *a.Image.DisplayName
}
return fmt.Sprintf(
"An image was created: '%v' (OCID: %v) in region '%v'",
a.Image.DisplayName, a.Image.ID, a.Region,
displayName, *a.Image.Id, a.Region,
)
}
@ -42,5 +47,5 @@ func (a *Artifact) State(name string) interface{} {
// Destroy deletes the custom image associated with the artifact.
func (a *Artifact) Destroy() error {
return a.driver.DeleteImage(a.Image.ID)
return a.driver.DeleteImage(*a.Image.Id)
}

View File

@ -7,11 +7,11 @@ import (
"log"
ocommon "github.com/hashicorp/packer/builder/oracle/common"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/oracle/oci-go-sdk/core"
)
// BuilderId uniquely identifies the builder
@ -78,10 +78,15 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, rawErr.(error)
}
region, err := b.config.ConfigProvider.Region()
if err != nil {
return nil, err
}
// Build the artifact and return it
artifact := &Artifact{
Image: state.Get("image").(client.Image),
Region: b.config.AccessCfg.Region,
Image: state.Get("image").(core.Image),
Region: region,
driver: driver,
}

View File

@ -1,216 +0,0 @@
package oci
import (
"bytes"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
const (
contentType = "Content-Type"
jsonContentType = "application/json"
)
// baseClient provides a basic (AND INTENTIONALLY INCOMPLETE) JSON REST client
// that abstracts away some of the repetitive code required in the OCI Client.
type baseClient struct {
httpClient *http.Client
method string
url string
queryStruct interface{}
header http.Header
body interface{}
}
// newBaseClient constructs a default baseClient.
func newBaseClient() *baseClient {
return &baseClient{
httpClient: http.DefaultClient,
method: "GET",
header: make(http.Header),
}
}
// New creates a copy of an existing baseClient.
func (c *baseClient) New() *baseClient {
// Copy headers
header := make(http.Header)
for k, v := range c.header {
header[k] = v
}
return &baseClient{
httpClient: c.httpClient,
method: c.method,
url: c.url,
header: header,
}
}
// Client sets the http Client used to perform requests.
func (c *baseClient) Client(httpClient *http.Client) *baseClient {
if httpClient == nil {
c.httpClient = http.DefaultClient
} else {
c.httpClient = httpClient
}
return c
}
// Base sets the base client url.
func (c *baseClient) Base(path string) *baseClient {
c.url = path
return c
}
// Path extends the client url.
func (c *baseClient) Path(path string) *baseClient {
baseURL, baseErr := url.Parse(c.url)
pathURL, pathErr := url.Parse(path)
// Bail on parsing error leaving the client's url unmodified
if baseErr != nil || pathErr != nil {
return c
}
c.url = baseURL.ResolveReference(pathURL).String()
return c
}
// QueryStruct sets the struct from which the request querystring is built.
func (c *baseClient) QueryStruct(params interface{}) *baseClient {
c.queryStruct = params
return c
}
// SetBody wraps a given struct for serialisation and sets the client body.
func (c *baseClient) SetBody(params interface{}) *baseClient {
c.body = params
return c
}
// Header
// AddHeader adds a HTTP header to the client. Existing keys will be extended.
func (c *baseClient) AddHeader(key, value string) *baseClient {
c.header.Add(key, value)
return c
}
// SetHeader sets a HTTP header on the client. Existing keys will be
// overwritten.
func (c *baseClient) SetHeader(key, value string) *baseClient {
c.header.Add(key, value)
return c
}
// HTTP methods (subset)
// Get sets the client's HTTP method to GET.
func (c *baseClient) Get(path string) *baseClient {
c.method = "GET"
return c.Path(path)
}
// Post sets the client's HTTP method to POST.
func (c *baseClient) Post(path string) *baseClient {
c.method = "POST"
return c.Path(path)
}
// Delete sets the client's HTTP method to DELETE.
func (c *baseClient) Delete(path string) *baseClient {
c.method = "DELETE"
return c.Path(path)
}
// Do executes a HTTP request and returns the response encoded as either error
// or success values.
func (c *baseClient) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) {
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
if successV != nil {
err = json.NewDecoder(resp.Body).Decode(successV)
}
} else {
if failureV != nil {
err = json.NewDecoder(resp.Body).Decode(failureV)
}
}
return resp, err
}
// Request builds a http.Request from the baseClient instance.
func (c *baseClient) Request() (*http.Request, error) {
reqURL, err := url.Parse(c.url)
if err != nil {
return nil, err
}
if c.queryStruct != nil {
err = addQueryStruct(reqURL, c.queryStruct)
if err != nil {
return nil, err
}
}
body := &bytes.Buffer{}
if c.body != nil {
if err := json.NewEncoder(body).Encode(c.body); err != nil {
return nil, err
}
}
req, err := http.NewRequest(c.method, reqURL.String(), body)
if err != nil {
return nil, err
}
// Add headers to request
for k, vs := range c.header {
for _, v := range vs {
req.Header.Add(k, v)
}
}
return req, nil
}
// Receive creates a http request from the client and executes it returning the
// response.
func (c *baseClient) Receive(successV, failureV interface{}) (*http.Response, error) {
req, err := c.Request()
if err != nil {
return nil, err
}
return c.Do(req, successV, failureV)
}
// addQueryStruct converts a struct to a querystring and merges any values
// provided in the URL itself.
func addQueryStruct(reqURL *url.URL, queryStruct interface{}) error {
urlValues, err := url.ParseQuery(reqURL.RawQuery)
if err != nil {
return err
}
queryValues, err := query.Values(queryStruct)
if err != nil {
return err
}
for k, vs := range queryValues {
for _, v := range vs {
urlValues.Add(k, v)
}
}
reqURL.RawQuery = urlValues.Encode()
return nil
}

View File

@ -1,31 +0,0 @@
package oci
import (
"net/http"
)
const (
apiVersion = "20160918"
userAgent = "go-oci/" + apiVersion
baseURLPattern = "https://%s.%s.oraclecloud.com/%s/"
)
// Client is the main interface through which consumers interact with the OCI
// API.
type Client struct {
UserAgent string
Compute *ComputeClient
Config *Config
}
// NewClient creates a new Client for communicating with the OCI API.
func NewClient(config *Config) (*Client, error) {
transport := NewTransport(http.DefaultTransport, config)
base := newBaseClient().Client(&http.Client{Transport: transport})
return &Client{
UserAgent: userAgent,
Compute: NewComputeClient(base.New().Base(config.getBaseURL("iaas"))),
Config: config,
}, nil
}

View File

@ -1,49 +0,0 @@
package oci
import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"github.com/go-ini/ini"
)
var (
mux *http.ServeMux
client *Client
server *httptest.Server
keyFile *os.File
)
// setup sets up a test HTTP server along with a oci.Client that is
// configured to talk to that test server. Tests should register handlers on
// mux which provide mock responses for the API method being tested.
func setup() {
mux = http.NewServeMux()
server = httptest.NewServer(mux)
parsedURL, _ := url.Parse(server.URL)
config := &Config{}
config.baseURL = parsedURL.String()
var cfg *ini.File
var err error
cfg, keyFile, err = BaseTestConfig()
config, err = loadConfigSection(cfg, "DEFAULT", config)
if err != nil {
panic(err)
}
client, err = NewClient(config)
if err != nil {
panic("Failed to instantiate test client")
}
}
// teardown closes the test HTTP server
func teardown() {
server.Close()
os.Remove(keyFile.Name())
}

View File

@ -1,21 +0,0 @@
package oci
// ComputeClient is a client for the OCI Compute API.
type ComputeClient struct {
BaseURL string
Instances *InstanceService
Images *ImageService
VNICAttachments *VNICAttachmentService
VNICs *VNICService
}
// NewComputeClient creates a new client for communicating with the OCI
// Compute API.
func NewComputeClient(s *baseClient) *ComputeClient {
return &ComputeClient{
Instances: NewInstanceService(s),
Images: NewImageService(s),
VNICAttachments: NewVNICAttachmentService(s),
VNICs: NewVNICService(s),
}
}

View File

@ -1,240 +0,0 @@
package oci
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"os"
"github.com/go-ini/ini"
"github.com/mitchellh/go-homedir"
)
// Config API authentication and target configuration
type Config struct {
// User OCID e.g. ocid1.user.oc1..aaaaaaaadcshyehbkvxl7arse3lv7z5oknexjgfhnhwidtugsxhlm4247
User string `ini:"user"`
// User's Tenancy OCID e.g. ocid1.tenancy.oc1..aaaaaaaagtgvshv6opxzjyzkupkt64ymd32n6kbomadanpcg43d
Tenancy string `ini:"tenancy"`
// Bare metal region identifier (e.g. us-phoenix-1)
Region string `ini:"region"`
// Hex key fingerprint (e.g. b5:a0:62:57:28:0d:fd:c9:59:16:eb:d4:51:9f:70:e4)
Fingerprint string `ini:"fingerprint"`
// Path to OCI config file (e.g. ~/.oci/config)
KeyFile string `ini:"key_file"`
// Passphrase used for the key, if it is encrypted.
PassPhrase string `ini:"pass_phrase"`
// Private key (loaded via LoadPrivateKey or ParsePrivateKey)
Key *rsa.PrivateKey
// Used to override base API URL.
baseURL string
}
// getBaseURL returns either the specified base URL or builds the appropriate
// URL based on service, region, and API version.
func (c *Config) getBaseURL(service string) string {
if c.baseURL != "" {
return c.baseURL
}
return fmt.Sprintf(baseURLPattern, service, c.Region, apiVersion)
}
// LoadConfigsFromFile loads all oracle oci configurations from a file
// (generally ~/.oci/config).
func LoadConfigsFromFile(path string) (map[string]*Config, error) {
if _, err := os.Stat(path); err != nil {
return nil, fmt.Errorf("Oracle OCI config file is missing: %s", path)
}
cfgFile, err := ini.Load(path)
if err != nil {
err := fmt.Errorf("Failed to parse config file %s: %s", path, err.Error())
return nil, err
}
configs := make(map[string]*Config)
// Load DEFAULT section to populate defaults for all other configs
config, err := loadConfigSection(cfgFile, "DEFAULT", nil)
if err != nil {
return nil, err
}
configs["DEFAULT"] = config
// Load other sections.
for _, sectionName := range cfgFile.SectionStrings() {
if sectionName == "DEFAULT" {
continue
}
// Map to Config struct with defaults from DEFAULT section.
config, err := loadConfigSection(cfgFile, sectionName, configs["DEFAULT"])
if err != nil {
return nil, err
}
configs[sectionName] = config
}
return configs, nil
}
// Loads an individual Config object from a ini.Section in the Oracle OCI config
// file.
func loadConfigSection(f *ini.File, sectionName string, config *Config) (*Config, error) {
if config == nil {
config = &Config{}
}
section, err := f.GetSection(sectionName)
if err != nil {
return nil, fmt.Errorf("Config file does not contain a %s section", sectionName)
}
if err := section.MapTo(config); err != nil {
return nil, err
}
config.Key, err = LoadPrivateKey(config)
if err != nil {
return nil, err
}
return config, err
}
// LoadPrivateKey loads private key from disk and parses it.
func LoadPrivateKey(config *Config) (*rsa.PrivateKey, error) {
// Expand '~' to $HOME
path, err := homedir.Expand(config.KeyFile)
if err != nil {
return nil, err
}
// Read and parse API signing key
keyContent, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
key, err := ParsePrivateKey(keyContent, []byte(config.PassPhrase))
return key, err
}
// ParsePrivateKey parses a PEM encoded array of bytes into an rsa.PrivateKey.
// Attempts to decrypt the PEM encoded array of bytes with the given password
// if the PEM encoded byte array is encrypted.
func ParsePrivateKey(content, password []byte) (*rsa.PrivateKey, error) {
keyBlock, _ := pem.Decode(content)
if keyBlock == nil {
return nil, errors.New("could not decode PEM private key")
}
var der []byte
var err error
if x509.IsEncryptedPEMBlock(keyBlock) {
if len(password) < 1 {
return nil, errors.New("encrypted private key but no pass phrase provided")
}
der, err = x509.DecryptPEMBlock(keyBlock, password)
if err != nil {
return nil, err
}
} else {
der = keyBlock.Bytes
}
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
return key, nil
}
key, err := x509.ParsePKCS8PrivateKey(der)
if err == nil {
switch key := key.(type) {
case *rsa.PrivateKey:
return key, nil
default:
return nil, errors.New("Private key is not an RSA private key")
}
}
return nil, fmt.Errorf("Failed to parse private key :%s", err)
}
// BaseTestConfig creates the base (DEFAULT) config including a temporary key
// file.
// NOTE: Caller is responsible for removing temporary key file.
func BaseTestConfig() (*ini.File, *os.File, error) {
keyFile, err := generateRSAKeyFile()
if err != nil {
return nil, keyFile, err
}
// Build ini
cfg := ini.Empty()
section, _ := cfg.NewSection("DEFAULT")
section.NewKey("region", "us-ashburn-1")
section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
section.NewKey("fingerprint", "3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55")
section.NewKey("key_file", keyFile.Name())
return cfg, keyFile, nil
}
// WriteTestConfig writes a ini.File to a temporary file for use in unit tests.
// NOTE: Caller is responsible for removing temporary file.
func WriteTestConfig(cfg *ini.File) (*os.File, error) {
confFile, err := ioutil.TempFile("", "config_file")
if err != nil {
return nil, err
}
_, err = cfg.WriteTo(confFile)
if err != nil {
os.Remove(confFile.Name())
return nil, err
}
return confFile, nil
}
// generateRSAKeyFile generates an RSA key file for use in unit tests.
// NOTE: The caller is responsible for deleting the temporary file.
func generateRSAKeyFile() (*os.File, error) {
// Create temporary file for the key
f, err := ioutil.TempFile("", "key")
if err != nil {
return nil, err
}
// Generate key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
return nil, err
}
// ASN.1 DER encoded form
privDer := x509.MarshalPKCS1PrivateKey(priv)
privBlk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: privDer,
}
// Write the key out
if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil {
return nil, err
}
return f, nil
}

View File

@ -1,283 +0,0 @@
package oci
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"os"
"reflect"
"strings"
"testing"
)
func TestNewConfigMissingFile(t *testing.T) {
// WHEN
_, err := LoadConfigsFromFile("some/invalid/path")
// THEN
if err == nil {
t.Error("Expected missing file error")
}
}
func TestNewConfigDefaultOnly(t *testing.T) {
// GIVEN
// Get DEFAULT config
cfg, keyFile, err := BaseTestConfig()
defer os.Remove(keyFile.Name())
// Write test config to file
f, err := WriteTestConfig(cfg)
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name()) // clean up
// WHEN
// Load configs
cfgs, err := LoadConfigsFromFile(f.Name())
if err != nil {
t.Fatal(err)
}
// THEN
if _, ok := cfgs["DEFAULT"]; !ok {
t.Fatal("Expected DEFAULT config to exist in map")
}
}
func TestNewConfigDefaultsPopulated(t *testing.T) {
// GIVEN
// Get DEFAULT config
cfg, keyFile, err := BaseTestConfig()
defer os.Remove(keyFile.Name())
admin := cfg.Section("ADMIN")
admin.NewKey("user", "ocid1.user.oc1..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
admin.NewKey("fingerprint", "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11")
// Write test config to file
f, err := WriteTestConfig(cfg)
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name()) // clean up
// WHEN
cfgs, err := LoadConfigsFromFile(f.Name())
adminConfig, ok := cfgs["ADMIN"]
// THEN
if !ok {
t.Fatal("Expected ADMIN config to exist in map")
}
if adminConfig.Region != "us-ashburn-1" {
t.Errorf("Expected 'us-ashburn-1', got '%s'", adminConfig.Region)
}
}
func TestNewConfigDefaultsOverridden(t *testing.T) {
// GIVEN
// Get DEFAULT config
cfg, keyFile, err := BaseTestConfig()
defer os.Remove(keyFile.Name())
admin := cfg.Section("ADMIN")
admin.NewKey("user", "ocid1.user.oc1..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
admin.NewKey("fingerprint", "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11")
// Write test config to file
f, err := WriteTestConfig(cfg)
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name()) // clean up
// WHEN
cfgs, err := LoadConfigsFromFile(f.Name())
adminConfig, ok := cfgs["ADMIN"]
// THEN
if !ok {
t.Fatal("Expected ADMIN config to exist in map")
}
if adminConfig.Fingerprint != "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11" {
t.Errorf("Expected fingerprint '11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11', got '%s'",
adminConfig.Fingerprint)
}
}
func TestParseEncryptedPrivateKeyValidPassword(t *testing.T) {
// Generate private key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
t.Fatalf("Unexpected generating RSA key: %+v", err)
}
publicKey := priv.PublicKey
// ASN.1 DER encoded form
privDer := x509.MarshalPKCS1PrivateKey(priv)
blockType := "RSA PRIVATE KEY"
password := []byte("password")
cipherType := x509.PEMCipherAES256
// Encrypt priv with password
encryptedPEMBlock, err := x509.EncryptPEMBlock(
rand.Reader,
blockType,
privDer,
password,
cipherType)
if err != nil {
t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
}
// Parse private key
key, err := ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), password)
if err != nil {
t.Fatalf("unexpected error: %+v", err)
}
// Check we get the same key back
if !reflect.DeepEqual(publicKey, key.PublicKey) {
t.Errorf("expected public key of encrypted and decrypted key to match")
}
}
func TestParseEncryptedPrivateKeyPKCS8(t *testing.T) {
// Generate private key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
t.Fatalf("Unexpected generating RSA key: %+v", err)
}
publicKey := priv.PublicKey
// Implements x509.MarshalPKCS8PrivateKey which is not included in the
// standard library.
pkey := struct {
Version int
PrivateKeyAlgorithm []asn1.ObjectIdentifier
PrivateKey []byte
}{
Version: 0,
PrivateKeyAlgorithm: []asn1.ObjectIdentifier{{1, 2, 840, 113549, 1, 1, 1}},
PrivateKey: x509.MarshalPKCS1PrivateKey(priv),
}
privDer, err := asn1.Marshal(pkey)
if err != nil {
t.Fatalf("Unexpected marshaling RSA key: %+v", err)
}
blockType := "RSA PRIVATE KEY"
password := []byte("password")
cipherType := x509.PEMCipherAES256
// Encrypt priv with password
encryptedPEMBlock, err := x509.EncryptPEMBlock(
rand.Reader,
blockType,
privDer,
password,
cipherType)
if err != nil {
t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
}
// Parse private key
key, err := ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), password)
if err != nil {
t.Fatalf("unexpected error: %+v", err)
}
// Check we get the same key back
if !reflect.DeepEqual(publicKey, key.PublicKey) {
t.Errorf("expected public key of encrypted and decrypted key to match")
}
}
func TestParseEncryptedPrivateKeyInvalidPassword(t *testing.T) {
// Generate private key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
t.Fatalf("Unexpected generating RSA key: %+v", err)
}
// ASN.1 DER encoded form
privDer := x509.MarshalPKCS1PrivateKey(priv)
blockType := "RSA PRIVATE KEY"
password := []byte("password")
cipherType := x509.PEMCipherAES256
// Encrypt priv with password
encryptedPEMBlock, err := x509.EncryptPEMBlock(
rand.Reader,
blockType,
privDer,
password,
cipherType)
if err != nil {
t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
}
// Parse private key (with wrong password)
_, err = ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), []byte("foo"))
if err == nil {
t.Fatalf("Expected error, got nil")
}
if !strings.Contains(err.Error(), "decryption password incorrect") {
t.Errorf("Expected error to contain 'decryption password incorrect', got %+v", err)
}
}
func TestParseEncryptedPrivateKeyInvalidNoPassword(t *testing.T) {
// Generate private key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
t.Fatalf("Unexpected generating RSA key: %+v", err)
}
// ASN.1 DER encoded form
privDer := x509.MarshalPKCS1PrivateKey(priv)
blockType := "RSA PRIVATE KEY"
password := []byte("password")
cipherType := x509.PEMCipherAES256
// Encrypt priv with password
encryptedPEMBlock, err := x509.EncryptPEMBlock(
rand.Reader,
blockType,
privDer,
password,
cipherType)
if err != nil {
t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
}
// Parse private key (with wrong password)
_, err = ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), []byte{})
if err == nil {
t.Fatalf("Expected error, got nil")
}
if !strings.Contains(err.Error(), "no pass phrase provided") {
t.Errorf("Expected error to contain 'no pass phrase provided', got %+v", err)
}
}

View File

@ -1,27 +0,0 @@
package oci
import "fmt"
// APIError encapsulates an error returned from the API
type APIError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (e APIError) Error() string {
return fmt.Sprintf("OCI: [%s] '%s'", e.Code, e.Message)
}
// firstError is a helper function to work out which error to return from calls
// to the API.
func firstError(err error, apiError *APIError) error {
if err != nil {
return err
}
if apiError != nil && len(apiError.Code) > 0 {
return apiError
}
return nil
}

View File

@ -1,122 +0,0 @@
package oci
import (
"time"
)
// ImageService enables communicating with the OCI compute API's instance
// related endpoints.
type ImageService struct {
client *baseClient
}
// NewImageService creates a new ImageService for communicating with the
// OCI compute API's instance related endpoints.
func NewImageService(s *baseClient) *ImageService {
return &ImageService{
client: s.New().Path("images/"),
}
}
// Image details a OCI boot disk image.
type Image struct {
// The OCID of the image originally used to launch the instance.
BaseImageID string `json:"baseImageId,omitempty"`
// The OCID of the compartment containing the instance you want to use
// as the basis for the image.
CompartmentID string `json:"compartmentId"`
// Whether instances launched with this image can be used to create new
// images.
CreateImageAllowed bool `json:"createImageAllowed"`
// A user-friendly name for the image. It does not have to be unique,
// and it's changeable. You cannot use an Oracle-provided image name
// as a custom image name.
DisplayName string `json:"displayName,omitempty"`
// The OCID of the image.
ID string `json:"id"`
// Current state of the image. Allowed values are:
// - PROVISIONING
// - AVAILABLE
// - DISABLED
// - DELETED
LifecycleState string `json:"lifecycleState"`
// The image's operating system (e.g. Oracle Linux).
OperatingSystem string `json:"operatingSystem"`
// The image's operating system version (e.g. 7.2).
OperatingSystemVersion string `json:"operatingSystemVersion"`
// The date and time the image was created.
TimeCreated time.Time `json:"timeCreated"`
}
// GetImageParams are the parameters available when communicating with the
// GetImage API endpoint.
type GetImageParams struct {
ID string `url:"imageId"`
}
// Get returns a single Image
func (s *ImageService) Get(params *GetImageParams) (Image, error) {
image := Image{}
e := &APIError{}
_, err := s.client.New().Get(params.ID).Receive(&image, e)
err = firstError(err, e)
return image, err
}
// CreateImageParams are the parameters available when communicating with
// the CreateImage API endpoint.
type CreateImageParams struct {
CompartmentID string `json:"compartmentId"`
DisplayName string `json:"displayName,omitempty"`
InstanceID string `json:"instanceId"`
}
// Create creates a new custom image based on a running compute instance. It
// does *not* wait for the imaging process to finish.
func (s *ImageService) Create(params *CreateImageParams) (Image, error) {
image := Image{}
e := &APIError{}
_, err := s.client.New().Post("").SetBody(params).Receive(&image, &e)
err = firstError(err, e)
return image, err
}
// GetResourceState GETs the LifecycleState of the given image id.
func (s *ImageService) GetResourceState(id string) (string, error) {
image, err := s.Get(&GetImageParams{ID: id})
if err != nil {
return "", err
}
return image.LifecycleState, nil
}
// DeleteImageParams are the parameters available when communicating with
// the DeleteImage API endpoint.
type DeleteImageParams struct {
ID string `url:"imageId"`
}
// Delete deletes an existing custom image.
// NOTE: Deleting an image results in the API endpoint returning 404 on
// subsequent calls. As such deletion can't be waited on with a Waiter.
func (s *ImageService) Delete(params *DeleteImageParams) error {
e := &APIError{}
_, err := s.client.New().Delete(params.ID).SetBody(params).Receive(nil, e)
err = firstError(err, e)
return err
}

View File

@ -1,115 +0,0 @@
package oci
import (
"fmt"
"net/http"
"reflect"
"testing"
)
func TestGetImage(t *testing.T) {
setup()
defer teardown()
id := "ocid1.image.oc1.phx.a"
path := fmt.Sprintf("/images/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"id":"%s"}`, id)
})
image, err := client.Compute.Images.Get(&GetImageParams{ID: id})
if err != nil {
t.Errorf("Client.Compute.Images.Get() returned error: %v", err)
}
want := Image{ID: id}
if !reflect.DeepEqual(image, want) {
t.Errorf("Client.Compute.Images.Get() returned %+v, want %+v", image, want)
}
}
func TestCreateImage(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/images/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"displayName": "go-oci test"}`)
})
params := &CreateImageParams{
CompartmentID: "ocid1.compartment.oc1..a",
DisplayName: "go-oci test image",
InstanceID: "ocid1.image.oc1.phx.a",
}
image, err := client.Compute.Images.Create(params)
if err != nil {
t.Errorf("Client.Compute.Images.Create() returned error: %v", err)
}
want := Image{DisplayName: "go-oci test"}
if !reflect.DeepEqual(image, want) {
t.Errorf("Client.Compute.Images.Create() returned %+v, want %+v", image, want)
}
}
func TestImageGetResourceState(t *testing.T) {
setup()
defer teardown()
id := "ocid1.image.oc1.phx.a"
path := fmt.Sprintf("/images/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"LifecycleState": "AVAILABLE"}`)
})
state, err := client.Compute.Images.GetResourceState(id)
if err != nil {
t.Errorf("Client.Compute.Images.GetResourceState() returned error: %v", err)
}
want := "AVAILABLE"
if state != want {
t.Errorf("Client.Compute.Images.GetResourceState() returned %+v, want %+v", state, want)
}
}
func TestImageGetResourceStateInvalidID(t *testing.T) {
setup()
defer teardown()
id := "ocid1.image.oc1.phx.a"
path := fmt.Sprintf("/images/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, `{"code": "NotAuthorizedOrNotFound"}`)
})
state, err := client.Compute.Images.GetResourceState(id)
if err == nil {
t.Errorf("Client.Compute.Images.GetResourceState() expected error, got %v", state)
}
want := &APIError{Code: "NotAuthorizedOrNotFound"}
if !reflect.DeepEqual(err, want) {
t.Errorf("Client.Compute.Images.GetResourceState() errored with %+v, want %+v", err, want)
}
}
func TestDeleteInstance(t *testing.T) {
setup()
defer teardown()
id := "ocid1.image.oc1.phx.a"
path := fmt.Sprintf("/images/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
err := client.Compute.Images.Delete(&DeleteImageParams{ID: id})
if err != nil {
t.Errorf("Client.Compute.Images.Delete() returned error: %v", err)
}
}

View File

@ -1,129 +0,0 @@
package oci
import (
"time"
)
// InstanceService enables communicating with the OCI compute API's instance
// related endpoints.
type InstanceService struct {
client *baseClient
}
// NewInstanceService creates a new InstanceService for communicating with the
// OCI compute API's instance related endpoints.
func NewInstanceService(s *baseClient) *InstanceService {
return &InstanceService{
client: s.New().Path("instances/"),
}
}
// Instance details a OCI compute instance.
type Instance struct {
// The Availability Domain the instance is running in.
AvailabilityDomain string `json:"availabilityDomain"`
// The OCID of the compartment that contains the instance.
CompartmentID string `json:"compartmentId"`
// A user-friendly name. Does not have to be unique, and it's changeable.
DisplayName string `json:"displayName,omitempty"`
// The OCID of the instance.
ID string `json:"id"`
// The image used to boot the instance.
ImageID string `json:"imageId,omitempty"`
// The current state of the instance. Allowed values:
// - PROVISIONING
// - RUNNING
// - STARTING
// - STOPPING
// - STOPPED
// - CREATING_IMAGE
// - TERMINATING
// - TERMINATED
LifecycleState string `json:"lifecycleState"`
// Custom metadata that you provide.
Metadata map[string]string `json:"metadata,omitempty"`
// The region that contains the Availability Domain the instance is running in.
Region string `json:"region"`
// The shape of the instance. The shape determines the number of CPUs
// and the amount of memory allocated to the instance.
Shape string `json:"shape"`
// The date and time the instance was created.
TimeCreated time.Time `json:"timeCreated"`
}
// GetInstanceParams are the parameters available when communicating with the
// GetInstance API endpoint.
type GetInstanceParams struct {
ID string `url:"instanceId,omitempty"`
}
// Get returns a single Instance
func (s *InstanceService) Get(params *GetInstanceParams) (Instance, error) {
instance := Instance{}
e := &APIError{}
_, err := s.client.New().Get(params.ID).Receive(&instance, e)
err = firstError(err, e)
return instance, err
}
// LaunchInstanceParams are the parameters available when communicating with
// the LunchInstance API endpoint.
type LaunchInstanceParams struct {
AvailabilityDomain string `json:"availabilityDomain,omitempty"`
CompartmentID string `json:"compartmentId,omitempty"`
DisplayName string `json:"displayName,omitempty"`
ImageID string `json:"imageId,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
OPCiPXEScript string `json:"opcIpxeScript,omitempty"`
Shape string `json:"shape,omitempty"`
SubnetID string `json:"subnetId,omitempty"`
}
// Launch creates a new OCI compute instance. It does *not* wait for the
// instance to boot.
func (s *InstanceService) Launch(params *LaunchInstanceParams) (Instance, error) {
instance := &Instance{}
e := &APIError{}
_, err := s.client.New().Post("").SetBody(params).Receive(instance, e)
err = firstError(err, e)
return *instance, err
}
// TerminateInstanceParams are the parameters available when communicating with
// the TerminateInstance API endpoint.
type TerminateInstanceParams struct {
ID string `url:"instanceId,omitempty"`
}
// Terminate terminates a running OCI compute instance.
// instance to boot.
func (s *InstanceService) Terminate(params *TerminateInstanceParams) error {
e := &APIError{}
_, err := s.client.New().Delete(params.ID).SetBody(params).Receive(nil, e)
err = firstError(err, e)
return err
}
// GetResourceState GETs the LifecycleState of the given instance id.
func (s *InstanceService) GetResourceState(id string) (string, error) {
instance, err := s.Get(&GetInstanceParams{ID: id})
if err != nil {
return "", err
}
return instance.LifecycleState, nil
}

View File

@ -1,96 +0,0 @@
package oci
import (
"fmt"
"net/http"
"reflect"
"testing"
)
func TestGetInstance(t *testing.T) {
setup()
defer teardown()
id := "ocid1.instance.oc1.phx.a"
path := fmt.Sprintf("/instances/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"id":"%s"}`, id)
})
instance, err := client.Compute.Instances.Get(&GetInstanceParams{ID: id})
if err != nil {
t.Errorf("Client.Compute.Instances.Get() returned error: %v", err)
}
want := Instance{ID: id}
if !reflect.DeepEqual(instance, want) {
t.Errorf("Client.Compute.Instances.Get() returned %+v, want %+v", instance, want)
}
}
func TestLaunchInstance(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/instances/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"displayName": "go-oci test"}`)
})
params := &LaunchInstanceParams{
AvailabilityDomain: "aaaa:PHX-AD-1",
CompartmentID: "ocid1.compartment.oc1..a",
DisplayName: "go-oci test",
ImageID: "ocid1.image.oc1.phx.a",
Shape: "VM.Standard1.1",
SubnetID: "ocid1.subnet.oc1.phx.a",
}
instance, err := client.Compute.Instances.Launch(params)
if err != nil {
t.Errorf("Client.Compute.Instances.Launch() returned error: %v", err)
}
want := Instance{DisplayName: "go-oci test"}
if !reflect.DeepEqual(instance, want) {
t.Errorf("Client.Compute.Instances.Launch() returned %+v, want %+v", instance, want)
}
}
func TestTerminateInstance(t *testing.T) {
setup()
defer teardown()
id := "ocid1.instance.oc1.phx.a"
path := fmt.Sprintf("/instances/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
err := client.Compute.Instances.Terminate(&TerminateInstanceParams{ID: id})
if err != nil {
t.Errorf("Client.Compute.Instances.Terminate() returned error: %v", err)
}
}
func TestInstanceGetResourceState(t *testing.T) {
setup()
defer teardown()
id := "ocid1.instance.oc1.phx.a"
path := fmt.Sprintf("/instances/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"LifecycleState": "RUNNING"}`)
})
state, err := client.Compute.Instances.GetResourceState(id)
if err != nil {
t.Errorf("Client.Compute.Instances.GetResourceState() returned error: %v", err)
}
want := "RUNNING"
if state != want {
t.Errorf("Client.Compute.Instances.GetResourceState() returned %+v, want %+v", state, want)
}
}

View File

@ -1,116 +0,0 @@
package oci
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
)
type nopCloser struct {
io.Reader
}
func (nopCloser) Close() error {
return nil
}
// Transport adds OCI signature authentication to each outgoing request.
type Transport struct {
transport http.RoundTripper
config *Config
}
// NewTransport creates a new Transport to add OCI signature authentication
// to each outgoing request.
func NewTransport(transport http.RoundTripper, config *Config) *Transport {
return &Transport{
transport: transport,
config: config,
}
}
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
var buf *bytes.Buffer
if req.Body != nil {
buf = new(bytes.Buffer)
buf.ReadFrom(req.Body)
req.Body = nopCloser{buf}
}
if req.Header.Get("date") == "" {
req.Header.Set("date", time.Now().UTC().Format(http.TimeFormat))
}
if req.Header.Get("content-type") == "" {
req.Header.Set("content-type", "application/json")
}
if req.Header.Get("accept") == "" {
req.Header.Set("accept", "application/json")
}
if req.Header.Get("host") == "" {
req.Header.Set("host", req.URL.Host)
}
var signheaders []string
if (req.Method == "PUT" || req.Method == "POST") && buf != nil {
signheaders = []string{"(request-target)", "host", "date",
"content-length", "content-type", "x-content-sha256"}
if req.Header.Get("content-length") == "" {
req.Header.Set("content-length", strconv.Itoa(buf.Len()))
}
hasher := sha256.New()
hasher.Write(buf.Bytes())
hash := hasher.Sum(nil)
req.Header.Set("x-content-sha256", base64.StdEncoding.EncodeToString(hash))
} else {
signheaders = []string{"date", "host", "(request-target)"}
}
var signbuffer bytes.Buffer
for idx, header := range signheaders {
signbuffer.WriteString(header)
signbuffer.WriteString(": ")
if header == "(request-target)" {
signbuffer.WriteString(strings.ToLower(req.Method))
signbuffer.WriteString(" ")
signbuffer.WriteString(req.URL.RequestURI())
} else {
signbuffer.WriteString(req.Header.Get(header))
}
if idx < len(signheaders)-1 {
signbuffer.WriteString("\n")
}
}
h := sha256.New()
h.Write(signbuffer.Bytes())
digest := h.Sum(nil)
signature, err := rsa.SignPKCS1v15(rand.Reader, t.config.Key, crypto.SHA256, digest)
if err != nil {
return nil, err
}
authHeader := fmt.Sprintf("Signature headers=\"%s\","+
"keyId=\"%s/%s/%s\","+
"algorithm=\"rsa-sha256\","+
"signature=\"%s\","+
"version=\"1\"",
strings.Join(signheaders, " "),
t.config.Tenancy, t.config.User, t.config.Fingerprint,
base64.StdEncoding.EncodeToString(signature))
req.Header.Add("Authorization", authHeader)
return t.transport.RoundTrip(req)
}

View File

@ -1,156 +0,0 @@
package oci
import (
"net/http"
"strings"
"testing"
)
const testKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAyLnyzmYj0dZuDo2nclIdEyLZrFZLtw5xFldWpCUl5W3SxKDL
iIgwxpSO75Yf++Rzqc5j6S5bpIrdca6AwVXCNmjjxMPO7vLLm4l4IUOZMv5FqKaC
I2plFz9uBkzGscnYnMbsDA430082E07lYpNv1xy8JwpbrIsqIMh4XCKci/Od5sLR
kEicmOpQK42FGRTQjjmQoWtv+9XED+vYTRL0AxQEC/6i/E7yssFXZ+fpHSKWeKTQ
K/1Fc4pZ1zNzJcDXGuweISx/QMLz78TAPH5OBq/EQzHKSpKvfnWFRyBHne8pwuN8
8wzbbD+/7OFjz28jNSERVJvfYe3X1k69IWMNGwIDAQABAoIBAQCZhcdU38AzxSrG
DMfuYymDslsEObiNWQlbig9lWlhCwx26cDVbxrZvm747NvpdgVyJmqbF+UP0dJVs
Voh51qrFTLIwk4bZMXBTFPCBmJ865knG9RuCFOUew8/WF7C82GHJf0eY7OL7xpDY
cbZ2D8gxofOydHSrYoElM88CwSI00xPCbBKEMrBO94oXC8yfp2bmV6bNhVXwFDEM
qda7M6jVAsBrTOzxUF5VdUUU/MLsu2cCk/ap1zer2Bml9Afk1bMeGJ3XDQgol0pS
CLxaGczpSNVMF9+pjA5sFHR5rmcl0b/kC9HsgOJGhLOimtS94O64dSdWifgsjf6+
fhT2SMiRAoGBAOUDwkdzNqQfvS+qrP2ULpB4vt7MZ70rDGmyMDLZ1VWgcm2cDIad
b7MkFG6GCa48mKkFXK9mOPyq8ELoTjZo2p+relEqf49BpaNxr+cp11pX7g0AkzCa
a8LwdOOUW/poqYl2xLuw9Rz6ky6ybzatMvCwpQCwnbAdABIVxz4oQKHpAoGBAOBg
3uYC/ynGdF9gJTfdS5XPYoLcKKRRspBZrvvDHaWyBnanm5KYwDAZPzLQMqcpyPeo
5xgwMmtNlc6lKKyGkhSLNCV+eO3yAx1h/cq7ityvMS7u6o5sq+/bvtEnbUPYbEtk
AhVD7/w5Yyzzi4beiQxDKe0q1mvUAH56aGqJivBjAoGBALmUMTPbDhUzTwg4Y1Rd
ZtpVrj43H31wS+++oEYktTZc/T0LLi9Llr9w5kmlvmR94CtfF/ted6FwF5/wRajb
kQXAXC83pAR/au0mbCeDhWpFRLculxfUmqxuVBozF9G0TGYDY2rA+++OsgQuPebt
tRDL4/nKJQ4Ygf0lvr4EulM5AoGBALoIdyabu3WmfhwJujH8P8wA+ztmUCgVOIio
YwWIe49C8Er2om1ESqxWcmit6CFi6qY0Gw6Z/2OqGxgPJY8NsBZqaBziJF+cdWqq
MWMiZXqdopi4LC9T+KZROn9tQhGrYfaL/5IkFti3t/uwHbH/1f8dvKhQCSGzz4kN
8n7KdTDjAoGAKh8XdIOQlThFK108VT2yp4BGZXEOvWrR19DLbuUzHVrEX+Bd+uFo
Ruk9iKEH7PSnlRnIvWc1y9qN7fUi5OR3LvQNGlXHyUl6CtmH3/b064bBKudC+XTn
VBelcIoGpH7Dn9I6pKUFauJz1TSbQCIjYGNqrjyzLtG+lH/gy5q4xs8=
-----END RSA PRIVATE KEY-----`
type testTarget struct {
CapturedReq *http.Request
Response *http.Response
}
func (target *testTarget) RoundTrip(req *http.Request) (*http.Response, error) {
target.CapturedReq = req
return target.Response, nil
}
func testReq(method string, url string, body string, headers map[string]string) *http.Request {
req, err := http.NewRequest(method, url, strings.NewReader(body))
if err != nil {
panic(err.Error())
}
for k, v := range headers {
req.Header.Add(k, v)
}
return req
}
var KnownGoodCases = []struct {
name string
inputRequest func() *http.Request
expectedHeaders map[string]string
}{
{
name: "Simple GET",
inputRequest: func() *http.Request {
return testReq("GET", "https://example.com/", "", map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT"})
},
expectedHeaders: map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT",
"content-type": "application/json",
"host": "example.com",
"accept": "application/json",
"Authorization": "Signature headers=\"date host (request-target)\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"UMw/FImQYZ5JBpfYcR9YN72lhupGl5yS+522NS9glLodU9f4oKRqaocpGdSUSRhhSDKxIx01rV547/HemJ6QqEPaJJuDQPXsGthokWMU2DBGyaMAqhLClgCJiRQMwpg4rdL2tETzkM3wy6UN+I52RYoNSdsnat2ZArCkfl8dIl9ydcwD8/+BqB8d2wyaAIS4iagdPKLAC/Mu9OzyUPOXQhYGYsoEdOowOUkHOlob65PFrlHmKJDdjEF3MDcygEpApItf4iUEloP5bjixAbZEVpj3HLQ5uaPx9m+RsLzYMeO0adE0wOv2YNmwZrExGhXh1BpTU33m5amHeUBxSaG+2A==\",version=\"1\"",
},
},
{
name: "Simple PUT request",
inputRequest: func() *http.Request {
return testReq("PUT", "https://example.com/", "Some Content", map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT"})
},
expectedHeaders: map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT",
"content-type": "application/json",
"content-length": "12",
"x-content-sha256": "lQ8fsURxamLtHxnwTYqd3MNYadJ4ZB/U9yQBKzu/fXA=",
"accept": "application/json",
"Authorization": "Signature headers=\"(request-target) host date content-length content-type x-content-sha256\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"FHyPt4PE2HGH+iftzcViB76pCJ2R9+DdTCo1Ss4mH4KHQJdyQtPsCpe6Dc19zie6cRr6dsenk21yYnncic8OwZhII8DULj2//qLFGmgFi84s7LJqMQ/COiP7O9KtCN+U8MMt4PV7ZDsiGFn3/8EUJ1wxYscxSIB19S1NpuEL062JgGfkqxTkTPd7V3Xh1NlmUUtQrAMR3l56k1iV0zXY9Uw0CjWYjueMP0JUmkO7zycYAVBrx7Q8wkmejlyD7yFrAnObyEsMm9cIL9IcruWFHeCHFxRLslw7AoLxibAm2Dc9EROuvCK2UkUp8AFkE+QyYDMrrSm1NLBMWdnYqdickA==\",version=\"1\"",
},
},
{
name: "Simple POST request",
inputRequest: func() *http.Request {
return testReq("POST", "https://example.com/", "Some Content", map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT"})
},
expectedHeaders: map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT",
"content-type": "application/json",
"content-length": "12",
"x-content-sha256": "lQ8fsURxamLtHxnwTYqd3MNYadJ4ZB/U9yQBKzu/fXA=",
"accept": "application/json",
"Authorization": "Signature headers=\"(request-target) host date content-length content-type x-content-sha256\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"WzGIoySkjqydwabMTxjVs05UBu0hThAEBzVs7HbYO45o2XpaoqGiNX67mNzs1PeYrGHpJp8+Ysoz66PChWV/1trxuTU92dQ/FgwvcwBRy5dQvdLkjWCZihNunSk4gt9652w6zZg/ybLon0CFbLRnlanDJDX9BgR3ttuTxf30t5qr2A4fnjFF4VjaU/CzE13cNfaWftjSd+xNcla2sbArF3R0+CEEb0xZEPzTyjjjkyvXdaPZwEprVn8IDmdJvLmRP4EniAPxE1EZIhd712M5ondQkR4/WckM44/hlKDeXGFb4y+QnU02i4IWgOWs3dh2tuzS1hp1zfq7qgPbZ4hp0A==\",version=\"1\"",
},
},
{
name: "Simple DELETE",
inputRequest: func() *http.Request {
return testReq("DELETE", "https://example.com/", "Some Content", map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT"})
},
expectedHeaders: map[string]string{
"date": "Mon, 26 Sep 2016 11:04:22 GMT",
"content-type": "application/json",
"accept": "application/json",
"Authorization": "Signature headers=\"date host (request-target)\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"Kj4YSpONZG1cibLbNgxIp4VoS5+80fsB2Fh2Ue28+QyXq4wwrJpMP+8jEupz1yTk1SNPYuxsk7lNOgtI6G1Hq0YJJVum74j46sUwRWe+f08tMJ3c9J+rrzLfpIrakQ8PaudLhHU0eK5kuTZme1dCwRWXvZq3r5IqkGot/OGMabKpBygRv9t0i5ry+bTslSjMqafTWLosY9hgIiGrXD+meB5tpyn+gPVYc//Hc/C7uNNgLJIMk5DKVa4U0YnoY3ojafZTXZQQNGRn2NDMcZUX3f3nJlUIfiZRiOCTkbPwx/fWb4MZtYaEsY5OPficbJRvfOBxSG1wjX+8rgO7ijhMAA==\",version=\"1\"",
},
},
}
func TestKnownGoodRequests(t *testing.T) {
pKey, err := ParsePrivateKey([]byte(testKey), []byte{})
if err != nil {
t.Fatalf("Failed to parse test key: %s", err.Error())
}
config := &Config{
Key: pKey,
User: "testuser",
Tenancy: "tenant",
Fingerprint: "3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55",
}
expectedResponse := &http.Response{}
for _, tt := range KnownGoodCases {
targetBackend := &testTarget{Response: expectedResponse}
target := NewTransport(targetBackend, config)
_, err = target.RoundTrip(tt.inputRequest())
if err != nil {
t.Fatalf("%s: Failed to handle request %s", tt.name, err.Error())
}
sentReq := targetBackend.CapturedReq
for header, val := range tt.expectedHeaders {
if sentReq.Header.Get(header) != val {
t.Fatalf("%s: Header mismatch in response,\n\t expecting \"%s\"\n\t got \"%s\"", tt.name, val, sentReq.Header.Get(header))
}
}
}
}

View File

@ -1,47 +0,0 @@
package oci
import (
"time"
)
// VNICService enables communicating with the OCI compute API's VNICs
// endpoint.
type VNICService struct {
client *baseClient
}
// NewVNICService creates a new VNICService for communicating with the
// OCI compute API's instance related endpoints.
func NewVNICService(s *baseClient) *VNICService {
return &VNICService{client: s.New().Path("vnics/")}
}
// VNIC - a virtual network interface card.
type VNIC struct {
AvailabilityDomain string `json:"availabilityDomain"`
CompartmentID string `json:"compartmentId"`
DisplayName string `json:"displayName,omitempty"`
ID string `json:"id"`
LifecycleState string `json:"lifecycleState"`
PrivateIP string `json:"privateIp"`
PublicIP string `json:"publicIp"`
SubnetID string `json:"subnetId"`
TimeCreated time.Time `json:"timeCreated"`
}
// GetVNICParams are the parameters available when communicating with the
// ListVNICs API endpoint.
type GetVNICParams struct {
ID string `url:"vnicId"`
}
// Get returns an individual VNIC.
func (s *VNICService) Get(params *GetVNICParams) (VNIC, error) {
VNIC := &VNIC{}
e := &APIError{}
_, err := s.client.New().Get(params.ID).Receive(VNIC, e)
err = firstError(err, e)
return *VNIC, err
}

View File

@ -1,52 +0,0 @@
package oci
import (
"time"
)
// VNICAttachmentService enables communicating with the OCI compute API's VNIC
// attachment endpoint.
type VNICAttachmentService struct {
client *baseClient
}
// NewVNICAttachmentService creates a new VNICAttachmentService for communicating with the
// OCI compute API's instance related endpoints.
func NewVNICAttachmentService(s *baseClient) *VNICAttachmentService {
return &VNICAttachmentService{
client: s.New().Path("vnicAttachments/"),
}
}
// VNICAttachment details the attachment of a VNIC to a OCI instance.
type VNICAttachment struct {
AvailabilityDomain string `json:"availabilityDomain"`
CompartmentID string `json:"compartmentId"`
DisplayName string `json:"displayName,omitempty"`
ID string `json:"id"`
InstanceID string `json:"instanceId"`
LifecycleState string `json:"lifecycleState"`
SubnetID string `json:"subnetId"`
TimeCreated time.Time `json:"timeCreated"`
VNICID string `json:"vnicId"`
}
// ListVnicAttachmentsParams are the parameters available when communicating
// with the ListVnicAttachments API endpoint.
type ListVnicAttachmentsParams struct {
AvailabilityDomain string `url:"availabilityDomain,omitempty"`
CompartmentID string `url:"compartmentId"`
InstanceID string `url:"instanceId,omitempty"`
VNICID string `url:"vnicId,omitempty"`
}
// List returns an array of VNICAttachments.
func (s *VNICAttachmentService) List(params *ListVnicAttachmentsParams) ([]VNICAttachment, error) {
vnicAttachments := new([]VNICAttachment)
e := new(APIError)
_, err := s.client.New().Get("").QueryStruct(params).Receive(vnicAttachments, e)
err = firstError(err, e)
return *vnicAttachments, err
}

View File

@ -1,31 +0,0 @@
package oci
import (
"fmt"
"net/http"
"reflect"
"testing"
)
func TestListVNICAttachments(t *testing.T) {
setup()
defer teardown()
id := "ocid1.image.oc1.phx.a"
mux.HandleFunc("/vnicAttachments/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `[{"id":"%s"}]`, id)
})
params := &ListVnicAttachmentsParams{InstanceID: id}
vnicAttachment, err := client.Compute.VNICAttachments.List(params)
if err != nil {
t.Errorf("Client.Compute.VNICAttachments.List() returned error: %v", err)
}
want := []VNICAttachment{{ID: id}}
if !reflect.DeepEqual(vnicAttachment, want) {
t.Errorf("Client.Compute.VNICAttachments.List() returned %+v, want %+v", vnicAttachment, want)
}
}

View File

@ -1,29 +0,0 @@
package oci
import (
"fmt"
"net/http"
"reflect"
"testing"
)
func TestGetVNIC(t *testing.T) {
setup()
defer teardown()
id := "ocid1.vnic.oc1.phx.a"
path := fmt.Sprintf("/vnics/%s", id)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"id": "%s"}`, id)
})
vnic, err := client.Compute.VNICs.Get(&GetVNICParams{ID: id})
if err != nil {
t.Errorf("Client.Compute.VNICs.Get() returned error: %v", err)
}
want := &VNIC{ID: id}
if reflect.DeepEqual(vnic, want) {
t.Errorf("Client.Compute.VNICs.Get() returned %+v, want %+v", vnic, want)
}
}

View File

@ -1,59 +0,0 @@
package oci
import (
"fmt"
"time"
)
const (
defaultWaitDurationMS = 5000
defaultMaxRetries = 0
)
type Waiter struct {
WaitDurationMS int
MaxRetries int
}
type WaitableService interface {
GetResourceState(id string) (string, error)
}
func stringSliceContains(slice []string, value string) bool {
for _, elem := range slice {
if elem == value {
return true
}
}
return false
}
// NewWaiter creates a waiter with default wait duration and unlimited retry
// operations.
func NewWaiter() *Waiter {
return &Waiter{WaitDurationMS: defaultWaitDurationMS, MaxRetries: defaultMaxRetries}
}
// WaitForResourceToReachState polls a resource that implements WaitableService
// repeatedly until it reaches a known state or fails if it reaches an
// unexpected state. The duration of the interval and number of polls is
// determined by the Waiter configuration.
func (w *Waiter) WaitForResourceToReachState(svc WaitableService, id string, waitStates []string, terminalState string) error {
for i := 0; w.MaxRetries == 0 || i < w.MaxRetries; i++ {
state, err := svc.GetResourceState(id)
if err != nil {
return err
}
if stringSliceContains(waitStates, state) {
time.Sleep(time.Duration(w.WaitDurationMS) * time.Millisecond)
continue
} else if state == terminalState {
return nil
}
return fmt.Errorf("Unexpected resource state %s, expecting a waiting state %s or terminal state %s ", state, waitStates, terminalState)
}
return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %s", w.MaxRetries, terminalState)
}

View File

@ -1,80 +0,0 @@
package oci
import (
"errors"
"fmt"
"testing"
)
const (
ValidID = "ID"
)
type testWaitSvc struct {
states []string
idx int
err error
}
func (tw *testWaitSvc) GetResourceState(id string) (string, error) {
if id != ValidID {
return "", fmt.Errorf("Invalid id %s", id)
}
if tw.err != nil {
return "", tw.err
}
if tw.idx >= len(tw.states) {
panic("Invalid test state")
}
state := tw.states[tw.idx]
tw.idx++
return state, nil
}
func TestReturnsWhenWaitStateIsReachedImmediately(t *testing.T) {
ws := &testWaitSvc{states: []string{"OK"}}
w := NewWaiter()
err := w.WaitForResourceToReachState(ws, ValidID, []string{}, "OK")
if err != nil {
t.Errorf("Failed to reach expected state, got %s", err)
}
}
func TestReturnsWhenResourceWaitsInValidWaitingState(t *testing.T) {
w := &Waiter{WaitDurationMS: 1, MaxRetries: defaultMaxRetries}
ws := &testWaitSvc{states: []string{"WAITING", "OK"}}
err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
if err != nil {
t.Errorf("Failed to reach expected state, got %s", err)
}
}
func TestPropagatesErrorFromGetter(t *testing.T) {
w := NewWaiter()
ws := &testWaitSvc{states: []string{}, err: errors.New("ERROR")}
err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
if err != ws.err {
t.Errorf("Expected error from getter got %s", err)
}
}
func TestReportsInvalidTransitionStateAsError(t *testing.T) {
w := NewWaiter()
tw := &testWaitSvc{states: []string{"UNKNOWN_STATE"}, err: errors.New("ERROR")}
err := w.WaitForResourceToReachState(tw, ValidID, []string{"WAITING"}, "OK")
if err == nil {
t.Fatal("Expected error from getter")
}
}
func TestErrorsWhenMaxWaitTriesExceeded(t *testing.T) {
w := Waiter{WaitDurationMS: 1, MaxRetries: 1}
ws := &testWaitSvc{states: []string{"WAITING", "OK"}}
err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
if err == nil {
t.Fatal("Expecting error but wait terminated")
}
}

View File

@ -9,12 +9,12 @@ import (
"os"
"path/filepath"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
ocicommon "github.com/oracle/oci-go-sdk/common"
"github.com/mitchellh/go-homedir"
)
@ -23,7 +23,7 @@ type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
AccessCfg *client.Config
ConfigProvider ocicommon.ConfigurationProvider
AccessCfgFile string `mapstructure:"access_cfg_file"`
AccessCfgFileAccount string `mapstructure:"access_cfg_file_account"`
@ -67,68 +67,54 @@ func NewConfig(raws ...interface{}) (*Config, error) {
}
// Determine where the SDK config is located
var accessCfgFile string
if c.AccessCfgFile != "" {
accessCfgFile = c.AccessCfgFile
} else {
accessCfgFile, err = getDefaultOCISettingsPath()
if c.AccessCfgFile == "" {
c.AccessCfgFile, err = getDefaultOCISettingsPath()
if err != nil {
accessCfgFile = "" // Access cfg might be in template
log.Println("Default OCI settings file not found")
}
}
accessCfg := &client.Config{}
if accessCfgFile != "" {
loadedAccessCfgs, err := client.LoadConfigsFromFile(accessCfgFile)
if err != nil {
return nil, fmt.Errorf("Invalid config file %s: %s", accessCfgFile, err)
}
cfgAccount := "DEFAULT"
if c.AccessCfgFileAccount != "" {
cfgAccount = c.AccessCfgFileAccount
}
var ok bool
accessCfg, ok = loadedAccessCfgs[cfgAccount]
if !ok {
return nil, fmt.Errorf("No account section '%s' found in config file %s", cfgAccount, accessCfgFile)
}
}
// Override SDK client config with any non-empty template properties
if c.UserID != "" {
accessCfg.User = c.UserID
}
if c.TenancyID != "" {
accessCfg.Tenancy = c.TenancyID
}
if c.Region != "" {
accessCfg.Region = c.Region
}
// Default if the template nor the API config contains a region.
if accessCfg.Region == "" {
accessCfg.Region = "us-phoenix-1"
}
if c.Fingerprint != "" {
accessCfg.Fingerprint = c.Fingerprint
}
if c.PassPhrase != "" {
accessCfg.PassPhrase = c.PassPhrase
if c.AccessCfgFileAccount == "" {
c.AccessCfgFileAccount = "DEFAULT"
}
var keyContent []byte
if c.KeyFile != "" {
accessCfg.KeyFile = c.KeyFile
accessCfg.Key, err = client.LoadPrivateKey(accessCfg)
path, err := homedir.Expand(c.KeyFile)
if err != nil {
return nil, fmt.Errorf("Failed to load private key %s : %s", accessCfg.KeyFile, err)
return nil, err
}
// Read API signing key
keyContent, err = ioutil.ReadFile(path)
if err != nil {
return nil, err
}
}
fileProvider, _ := ocicommon.ConfigurationProviderFromFileWithProfile(c.AccessCfgFile, c.AccessCfgFileAccount, c.PassPhrase)
if c.Region == "" {
var region string
if fileProvider != nil {
region, _ = fileProvider.Region()
}
if region == "" {
c.Region = "us-phoenix-1"
}
}
providers := []ocicommon.ConfigurationProvider{
NewRawConfigurationProvider(c.TenancyID, c.UserID, c.Region, c.Fingerprint, string(keyContent), &c.PassPhrase),
}
if fileProvider != nil {
providers = append(providers, fileProvider)
}
// Load API access configuration from SDK
configProvider, err := ocicommon.ComposingConfigurationProvider(providers)
if err != nil {
return nil, err
}
var errs *packer.MultiError
@ -136,44 +122,36 @@ func NewConfig(raws ...interface{}) (*Config, error) {
errs = packer.MultiErrorAppend(errs, es...)
}
// Required AccessCfg configuration options
if accessCfg.User == "" {
if userOCID, _ := configProvider.UserOCID(); userOCID == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("'user_ocid' must be specified"))
}
if accessCfg.Tenancy == "" {
tenancyOCID, _ := configProvider.TenancyOCID()
if tenancyOCID == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("'tenancy_ocid' must be specified"))
}
if accessCfg.Region == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("'region' must be specified"))
}
if accessCfg.Fingerprint == "" {
if fingerprint, _ := configProvider.KeyFingerprint(); fingerprint == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("'fingerprint' must be specified"))
}
if accessCfg.Key == nil {
if _, err := configProvider.PrivateRSAKey(); err != nil {
errs = packer.MultiErrorAppend(
errs, errors.New("'key_file' must be specified"))
}
c.AccessCfg = accessCfg
// Required non AccessCfg configuration options
c.ConfigProvider = configProvider
if c.AvailabilityDomain == "" {
errs = packer.MultiErrorAppend(
errs, errors.New("'availability_domain' must be specified"))
}
if c.CompartmentID == "" {
c.CompartmentID = accessCfg.Tenancy
if c.CompartmentID == "" && tenancyOCID != "" {
c.CompartmentID = tenancyOCID
}
if c.Shape == "" {

View File

@ -0,0 +1,76 @@
package oci
import (
"crypto/rsa"
"errors"
"fmt"
"github.com/oracle/oci-go-sdk/common"
)
// rawConfigurationProvider allows a user to simply construct a configuration
// provider from raw values. It errors on access when those values are empty.
type rawConfigurationProvider struct {
tenancy string
user string
region string
fingerprint string
privateKey string
privateKeyPassphrase *string
}
// NewRawConfigurationProvider will create a rawConfigurationProvider.
func NewRawConfigurationProvider(tenancy, user, region, fingerprint, privateKey string, privateKeyPassphrase *string) common.ConfigurationProvider {
return rawConfigurationProvider{tenancy, user, region, fingerprint, privateKey, privateKeyPassphrase}
}
func (p rawConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
return common.PrivateKeyFromBytes([]byte(p.privateKey), p.privateKeyPassphrase)
}
func (p rawConfigurationProvider) KeyID() (keyID string, err error) {
tenancy, err := p.TenancyOCID()
if err != nil {
return
}
user, err := p.UserOCID()
if err != nil {
return
}
fingerprint, err := p.KeyFingerprint()
if err != nil {
return
}
return fmt.Sprintf("%s/%s/%s", tenancy, user, fingerprint), nil
}
func (p rawConfigurationProvider) TenancyOCID() (string, error) {
if p.tenancy == "" {
return "", errors.New("no tenancy provided")
}
return p.tenancy, nil
}
func (p rawConfigurationProvider) UserOCID() (string, error) {
if p.user == "" {
return "", errors.New("no user provided")
}
return p.user, nil
}
func (p rawConfigurationProvider) KeyFingerprint() (string, error) {
if p.fingerprint == "" {
return "", errors.New("no fingerprint provided")
}
return p.fingerprint, nil
}
func (p rawConfigurationProvider) Region() (string, error) {
if p.region == "" {
return "", errors.New("no region provided")
}
return p.region, nil
}

View File

@ -1,13 +1,16 @@
package oci
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"io/ioutil"
"os"
"reflect"
"strings"
"testing"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
"github.com/go-ini/ini"
)
func testConfig(accessConfFile *os.File) map[string]interface{} {
@ -29,22 +32,16 @@ func testConfig(accessConfFile *os.File) map[string]interface{} {
}
}
func getField(c *client.Config, field string) string {
r := reflect.ValueOf(c)
f := reflect.Indirect(r).FieldByName(field)
return string(f.String())
}
func TestConfig(t *testing.T) {
// Shared set-up and defered deletion
cfg, keyFile, err := client.BaseTestConfig()
cfg, keyFile, err := baseTestConfigWithTmpKeyFile()
if err != nil {
t.Fatal(err)
}
defer os.Remove(keyFile.Name())
cfgFile, err := client.WriteTestConfig(cfg)
cfgFile, err := writeTestConfig(cfg)
if err != nil {
t.Fatal(err)
}
@ -55,7 +52,7 @@ func TestConfig(t *testing.T) {
tmpHome, err := ioutil.TempDir("", "packer_config_test")
if err != nil {
t.Fatalf("err: %+v", err)
t.Fatalf("Unexpected error when creating temporary directory: %+v", err)
}
defer os.Remove(tmpHome)
@ -64,15 +61,13 @@ func TestConfig(t *testing.T) {
defer os.Setenv("HOME", home)
// Config tests
t.Run("BaseConfig", func(t *testing.T) {
raw := testConfig(cfgFile)
_, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("err: %+v", errs)
t.Fatalf("Unexpected error in configuration %+v", errs)
}
})
t.Run("NoAccessConfig", func(t *testing.T) {
@ -81,14 +76,14 @@ func TestConfig(t *testing.T) {
_, errs := NewConfig(raw)
s := errs.Error()
expectedErrors := []string{
"'user_ocid'", "'tenancy_ocid'", "'fingerprint'",
"'key_file'",
"'user_ocid'", "'tenancy_ocid'", "'fingerprint'", "'key_file'",
}
s := errs.Error()
for _, expected := range expectedErrors {
if !strings.Contains(s, expected) {
t.Errorf("Expected %s to contain '%s'", s, expected)
t.Errorf("Expected %q to contain '%s'", s, expected)
}
}
})
@ -113,12 +108,17 @@ func TestConfig(t *testing.T) {
raw := testConfig(cfgFile)
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("err: %+v", errs)
t.Fatalf("Unexpected error in configuration %+v", errs)
}
expected := "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
if c.AccessCfg.Tenancy != expected {
t.Errorf("Expected tenancy: %s, got %s.", expected, c.AccessCfg.Tenancy)
tenancy, err := c.ConfigProvider.TenancyOCID()
if err != nil {
t.Fatalf("Unexpected error getting tenancy ocid: %v", err)
}
expected := "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
if tenancy != expected {
t.Errorf("Expected tenancy: %s, got %s.", expected, tenancy)
}
})
@ -127,12 +127,17 @@ func TestConfig(t *testing.T) {
raw := testConfig(cfgFile)
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("err: %+v", errs)
t.Fatalf("Unexpected error in configuration %+v", errs)
}
region, err := c.ConfigProvider.Region()
if err != nil {
t.Fatalf("Unexpected error getting region: %v", err)
}
expected := "us-ashburn-1"
if c.AccessCfg.Region != expected {
t.Errorf("Expected region: %s, got %s.", expected, c.AccessCfg.Region)
if region != expected {
t.Errorf("Expected region: %s, got %s.", expected, region)
}
})
@ -159,7 +164,7 @@ func TestConfig(t *testing.T) {
c, errs := NewConfig(raw)
if errs != nil {
t.Errorf("Unexpected error(s): %s", errs)
t.Fatalf("Unexpected error in configuration %+v", errs)
}
if !strings.Contains(c.ImageName, "packer-") {
@ -167,30 +172,138 @@ func TestConfig(t *testing.T) {
}
})
// Test that AccessCfgFile properties are overridden by their
// corresponding template keys.
accessOverrides := map[string]string{
"user_ocid": "User",
"tenancy_ocid": "Tenancy",
"region": "Region",
"fingerprint": "Fingerprint",
}
for k, v := range accessOverrides {
t.Run("AccessCfg."+v+"Overridden", func(t *testing.T) {
expected := "override"
t.Run("user_ocid_overridden", func(t *testing.T) {
expected := "override"
raw := testConfig(cfgFile)
raw["user_ocid"] = expected
raw := testConfig(cfgFile)
raw[k] = expected
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("Unexpected error in configuration %+v", errs)
}
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("err: %+v", errs)
}
user, _ := c.ConfigProvider.UserOCID()
if user != expected {
t.Errorf("Expected ConfigProvider.UserOCID: %s, got %s", expected, user)
}
})
accessVal := getField(c.AccessCfg, v)
if accessVal != expected {
t.Errorf("Expected AccessCfg.%s: %s, got %s", v, expected, accessVal)
}
})
}
t.Run("tenancy_ocid_overidden", func(t *testing.T) {
expected := "override"
raw := testConfig(cfgFile)
raw["tenancy_ocid"] = expected
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("Unexpected error in configuration %+v", errs)
}
tenancy, _ := c.ConfigProvider.TenancyOCID()
if tenancy != expected {
t.Errorf("Expected ConfigProvider.TenancyOCID: %s, got %s", expected, tenancy)
}
})
t.Run("region_overidden", func(t *testing.T) {
expected := "override"
raw := testConfig(cfgFile)
raw["region"] = expected
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("Unexpected error in configuration %+v", errs)
}
region, _ := c.ConfigProvider.Region()
if region != expected {
t.Errorf("Expected ConfigProvider.Region: %s, got %s", expected, region)
}
})
t.Run("fingerprint_overidden", func(t *testing.T) {
expected := "override"
raw := testConfig(cfgFile)
raw["fingerprint"] = expected
c, errs := NewConfig(raw)
if errs != nil {
t.Fatalf("Unexpected error in configuration: %+v", errs)
}
fingerprint, _ := c.ConfigProvider.KeyFingerprint()
if fingerprint != expected {
t.Errorf("Expected ConfigProvider.KeyFingerprint: %s, got %s", expected, fingerprint)
}
})
}
// BaseTestConfig creates the base (DEFAULT) config including a temporary key
// file.
// NOTE: Caller is responsible for removing temporary key file.
func baseTestConfigWithTmpKeyFile() (*ini.File, *os.File, error) {
keyFile, err := generateRSAKeyFile()
if err != nil {
return nil, keyFile, err
}
// Build ini
cfg := ini.Empty()
section, _ := cfg.NewSection("DEFAULT")
section.NewKey("region", "us-ashburn-1")
section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
section.NewKey("fingerprint", "70:04:5z:b3:19:ab:90:75:a4:1f:50:d4:c7:c3:33:20")
section.NewKey("key_file", keyFile.Name())
return cfg, keyFile, nil
}
// WriteTestConfig writes a ini.File to a temporary file for use in unit tests.
// NOTE: Caller is responsible for removing temporary file.
func writeTestConfig(cfg *ini.File) (*os.File, error) {
confFile, err := ioutil.TempFile("", "config_file")
if err != nil {
return nil, err
}
if _, err := confFile.Write([]byte("[DEFAULT]\n")); err != nil {
os.Remove(confFile.Name())
return nil, err
}
if _, err := cfg.WriteTo(confFile); err != nil {
os.Remove(confFile.Name())
return nil, err
}
return confFile, nil
}
// generateRSAKeyFile generates an RSA key file for use in unit tests.
// NOTE: The caller is responsible for deleting the temporary file.
func generateRSAKeyFile() (*os.File, error) {
// Create temporary file for the key
f, err := ioutil.TempFile("", "key")
if err != nil {
return nil, err
}
// Generate key
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
return nil, err
}
// ASN.1 DER encoded form
privDer := x509.MarshalPKCS1PrivateKey(priv)
privBlk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: privDer,
}
// Write the key out
if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil {
return nil, err
}
return f, nil
}

View File

@ -1,13 +1,11 @@
package oci
import (
client "github.com/hashicorp/packer/builder/oracle/oci/client"
)
import "github.com/oracle/oci-go-sdk/core"
// Driver interfaces between the builder steps and the OCI SDK.
type Driver interface {
CreateInstance(publicKey string) (string, error)
CreateImage(id string) (client.Image, error)
CreateImage(id string) (core.Image, error)
DeleteImage(id string) error
GetInstanceIP(id string) (string, error)
TerminateInstance(id string) error

View File

@ -1,8 +1,6 @@
package oci
import (
client "github.com/hashicorp/packer/builder/oracle/oci/client"
)
import "github.com/oracle/oci-go-sdk/core"
// driverMock implements the Driver interface and communicates with Oracle
// OCI.
@ -40,12 +38,12 @@ func (d *driverMock) CreateInstance(publicKey string) (string, error) {
}
// CreateImage creates a new custom image.
func (d *driverMock) CreateImage(id string) (client.Image, error) {
func (d *driverMock) CreateImage(id string) (core.Image, error) {
if d.CreateImageErr != nil {
return client.Image{}, d.CreateImageErr
return core.Image{}, d.CreateImageErr
}
d.CreateImageID = id
return client.Image{ID: id}, nil
return core.Image{Id: &id}, nil
}
// DeleteImage mocks deleting a custom image.

View File

@ -1,123 +1,191 @@
package oci
import (
"context"
"errors"
"fmt"
"time"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
core "github.com/oracle/oci-go-sdk/core"
)
// driverOCI implements the Driver interface and communicates with Oracle
// OCI.
type driverOCI struct {
client *client.Client
cfg *Config
computeClient core.ComputeClient
vcnClient core.VirtualNetworkClient
cfg *Config
}
// NewDriverOCI Creates a new driverOCI with a connected client.
// NewDriverOCI Creates a new driverOCI with a connected compute client and a connected vcn client.
func NewDriverOCI(cfg *Config) (Driver, error) {
client, err := client.NewClient(cfg.AccessCfg)
coreClient, err := core.NewComputeClientWithConfigurationProvider(cfg.ConfigProvider)
if err != nil {
return nil, err
}
return &driverOCI{client: client, cfg: cfg}, nil
vcnClient, err := core.NewVirtualNetworkClientWithConfigurationProvider(cfg.ConfigProvider)
if err != nil {
return nil, err
}
return &driverOCI{
computeClient: coreClient,
vcnClient: vcnClient,
cfg: cfg,
}, nil
}
// CreateInstance creates a new compute instance.
func (d *driverOCI) CreateInstance(publicKey string) (string, error) {
params := &client.LaunchInstanceParams{
AvailabilityDomain: d.cfg.AvailabilityDomain,
CompartmentID: d.cfg.CompartmentID,
ImageID: d.cfg.BaseImageID,
Shape: d.cfg.Shape,
SubnetID: d.cfg.SubnetID,
Metadata: map[string]string{
"ssh_authorized_keys": publicKey,
},
metadata := map[string]string{
"ssh_authorized_keys": publicKey,
}
if d.cfg.UserData != "" {
params.Metadata["user_data"] = d.cfg.UserData
metadata["user_data"] = d.cfg.UserData
}
instance, err := d.client.Compute.Instances.Launch(params)
instance, err := d.computeClient.LaunchInstance(context.TODO(), core.LaunchInstanceRequest{LaunchInstanceDetails: core.LaunchInstanceDetails{
AvailabilityDomain: &d.cfg.AvailabilityDomain,
CompartmentId: &d.cfg.CompartmentID,
ImageId: &d.cfg.BaseImageID,
Shape: &d.cfg.Shape,
SubnetId: &d.cfg.SubnetID,
Metadata: metadata,
}})
if err != nil {
return "", err
}
return instance.ID, nil
return *instance.Id, nil
}
// CreateImage creates a new custom image.
func (d *driverOCI) CreateImage(id string) (client.Image, error) {
params := &client.CreateImageParams{
CompartmentID: d.cfg.CompartmentID,
InstanceID: id,
DisplayName: d.cfg.ImageName,
}
image, err := d.client.Compute.Images.Create(params)
func (d *driverOCI) CreateImage(id string) (core.Image, error) {
res, err := d.computeClient.CreateImage(context.TODO(), core.CreateImageRequest{CreateImageDetails: core.CreateImageDetails{
CompartmentId: &d.cfg.CompartmentID,
InstanceId: &id,
DisplayName: &d.cfg.ImageName,
}})
if err != nil {
return client.Image{}, err
return core.Image{}, err
}
return image, nil
return res.Image, nil
}
// DeleteImage deletes a custom image.
func (d *driverOCI) DeleteImage(id string) error {
return d.client.Compute.Images.Delete(&client.DeleteImageParams{ID: id})
_, err := d.computeClient.DeleteImage(context.TODO(), core.DeleteImageRequest{ImageId: &id})
return err
}
// GetInstanceIP returns the public or private IP corresponding to the given instance id.
func (d *driverOCI) GetInstanceIP(id string) (string, error) {
// get nvic and cross ref to find pub ip address
vnics, err := d.client.Compute.VNICAttachments.List(
&client.ListVnicAttachmentsParams{
InstanceID: id,
CompartmentID: d.cfg.CompartmentID,
},
)
vnics, err := d.computeClient.ListVnicAttachments(context.TODO(), core.ListVnicAttachmentsRequest{
InstanceId: &id,
CompartmentId: &d.cfg.CompartmentID,
})
if err != nil {
return "", err
}
if len(vnics) < 1 {
if len(vnics.Items) == 0 {
return "", errors.New("instance has zero VNICs")
}
vnic, err := d.client.Compute.VNICs.Get(&client.GetVNICParams{ID: vnics[0].VNICID})
vnic, err := d.vcnClient.GetVnic(context.TODO(), core.GetVnicRequest{VnicId: vnics.Items[0].VnicId})
if err != nil {
return "", fmt.Errorf("Error getting VNIC details: %s", err)
}
if d.cfg.UsePrivateIP {
return vnic.PrivateIP, nil
return *vnic.PrivateIp, nil
}
return vnic.PublicIP, nil
if vnic.PublicIp == nil {
return "", fmt.Errorf("Error getting VNIC Public Ip for: %s", id)
}
return *vnic.PublicIp, nil
}
// TerminateInstance terminates a compute instance.
func (d *driverOCI) TerminateInstance(id string) error {
params := &client.TerminateInstanceParams{ID: id}
return d.client.Compute.Instances.Terminate(params)
_, err := d.computeClient.TerminateInstance(context.TODO(), core.TerminateInstanceRequest{
InstanceId: &id,
})
return err
}
// WaitForImageCreation waits for a provisioning custom image to reach the
// "AVAILABLE" state.
func (d *driverOCI) WaitForImageCreation(id string) error {
return client.NewWaiter().WaitForResourceToReachState(
d.client.Compute.Images,
return waitForResourceToReachState(
func(string) (string, error) {
image, err := d.computeClient.GetImage(context.TODO(), core.GetImageRequest{ImageId: &id})
if err != nil {
return "", err
}
return string(image.LifecycleState), nil
},
id,
[]string{"PROVISIONING"},
"AVAILABLE",
0, //Unlimited Retries
5*time.Second, //5 second wait between retries
)
}
// WaitForInstanceState waits for an instance to reach the a given terminal
// state.
func (d *driverOCI) WaitForInstanceState(id string, waitStates []string, terminalState string) error {
return client.NewWaiter().WaitForResourceToReachState(
d.client.Compute.Instances,
return waitForResourceToReachState(
func(string) (string, error) {
instance, err := d.computeClient.GetInstance(context.TODO(), core.GetInstanceRequest{InstanceId: &id})
if err != nil {
return "", err
}
return string(instance.LifecycleState), nil
},
id,
waitStates,
terminalState,
0, //Unlimited Retries
5*time.Second, //5 second wait between retries
)
}
// WaitForResourceToReachState checks the response of a request through a
// polled get and waits until the desired state or until the max retried has
// been reached.
func waitForResourceToReachState(getResourceState func(string) (string, error), id string, waitStates []string, terminalState string, maxRetries int, waitDuration time.Duration) error {
for i := 0; maxRetries == 0 || i < maxRetries; i++ {
state, err := getResourceState(id)
if err != nil {
return err
}
if stringSliceContains(waitStates, state) {
time.Sleep(waitDuration)
continue
} else if state == terminalState {
return nil
}
return fmt.Errorf("Unexpected resource state %q, expecting a waiting state %s or terminal state %q ", state, waitStates, terminalState)
}
return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %q", maxRetries, terminalState)
}
// stringSliceContains loops through a slice of strings returning a boolean
// based on whether a given value is contained in the slice.
func stringSliceContains(slice []string, value string) bool {
for _, elem := range slice {
if elem == value {
return true
}
}
return false
}

View File

@ -27,7 +27,7 @@ func (s *stepImage) Run(_ context.Context, state multistep.StateBag) multistep.S
return multistep.ActionHalt
}
err = driver.WaitForImageCreation(image.ID)
err = driver.WaitForImageCreation(*image.Id)
if err != nil {
err = fmt.Errorf("Error waiting for image creation to finish: %s", err)
ui.Error(err.Error())

View File

@ -6,33 +6,32 @@ import (
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
client "github.com/hashicorp/packer/builder/oracle/oci/client"
)
// TODO(apryde): It would be good not to have to write a key file to disk to
// load the config.
func baseTestConfig() *Config {
_, keyFile, err := client.BaseTestConfig()
_, keyFile, err := baseTestConfigWithTmpKeyFile()
if err != nil {
panic(err)
}
cfg, err := NewConfig(map[string]interface{}{
"availability_domain": "aaaa:PHX-AD-3",
"availability_domain": "aaaa:US-ASHBURN-AD-1",
// Image
"base_image_ocid": "ocd1...",
"base_image_ocid": "ocid1.image.oc1.iad.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"shape": "VM.Standard1.1",
"image_name": "HelloWorld",
"region": "us-ashburn-1",
// Networking
"subnet_ocid": "ocd1...",
"subnet_ocid": "ocid1.subnet.oc1.iad.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
// AccessConfig
"user_ocid": "ocid1...",
"tenancy_ocid": "ocid1...",
"fingerprint": "00:00...",
"user_ocid": "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"tenancy_ocid": "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"fingerprint": "70:04:5z:b3:19:ab:90:75:a4:1f:50:d4:c7:c3:33:20",
"key_file": keyFile.Name(),
// Comm

15
vendor/github.com/oracle/oci-go-sdk/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,15 @@
# CHANGELOG
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
## 1.0.0 - 2018-02-28 Initial Release
### Added
- Support for Audit service
- Support for Core Services (Networking, Compute, Block Volume)
- Support for Database service
- Support for IAM service
- Support for Load Balancing service
- Suport for Object Storage service

24
vendor/github.com/oracle/oci-go-sdk/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,24 @@
# Contributing to the Oracle Cloud Infrastructure Go SDK
*Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.*
Pull requests can be made under
[The Oracle Contributor Agreement](https://www.oracle.com/technetwork/community/oca-486395.html)
(OCA).
For pull requests to be accepted, the bottom of
your commit message must have the following line using your name and
e-mail address as it appears in the OCA Signatories list.
```
Signed-off-by: Your Name <you@example.org>
```
This can be automatically added to pull requests by committing with:
```
git commit --signoff
````
Only pull requests from committers that can be verified as having
signed the OCA can be accepted.

82
vendor/github.com/oracle/oci-go-sdk/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,82 @@
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
This software is dual-licensed to you under the Universal Permissive License (UPL) and Apache License 2.0.  See below for license terms.  You may choose either license, or both.
 ____________________________
The Universal Permissive License (UPL), Version 1.0
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both
(a) the Software, and
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a "Larger Work" to which the Software is contributed by such licensors),
without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms.
This license is subject to the following condition:
The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The Apache Software License, Version 2.0
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); You may not use this product except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. A copy of the license is also reproduced below. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

55
vendor/github.com/oracle/oci-go-sdk/Makefile generated vendored Normal file
View File

@ -0,0 +1,55 @@
DOC_SERVER_URL=https:\/\/docs.us-phoenix-1.oraclecloud.com
GEN_TARGETS = identity core objectstorage loadbalancer database audit
NON_GEN_TARGETS = common common/auth
TARGETS = $(NON_GEN_TARGETS) $(GEN_TARGETS)
TARGETS_WITH_TESTS = common common/auth
TARGETS_BUILD = $(patsubst %,build-%, $(TARGETS))
TARGETS_CLEAN = $(patsubst %,clean-%, $(GEN_TARGETS))
TARGETS_LINT = $(patsubst %,lint-%, $(TARGETS))
TARGETS_TEST = $(patsubst %,test-%, $(TARGETS_WITH_TESTS))
TARGETS_RELEASE= $(patsubst %,release-%, $(TARGETS))
GOLINT=$(GOPATH)/bin/golint
LINT_FLAGS=-min_confidence 0.9 -set_exit_status
.PHONY: $(TARGETS_BUILD) $(TARGET_TEST)
build: lint $(TARGETS_BUILD)
test: build $(TARGETS_TEST)
lint: $(TARGETS_LINT)
clean: $(TARGETS_CLEAN)
$(TARGETS_LINT): lint-%:%
@echo "linting and formatting: $<"
@(cd $< && gofmt -s -w .)
@if [ \( $< = common \) -o \( $< = common/auth \) ]; then\
(cd $< && $(GOLINT) -set_exit_status .);\
else\
(cd $< && $(GOLINT) $(LINT_FLAGS) .);\
fi
$(TARGETS_BUILD): build-%:%
@echo "building: $<"
@(cd $< && find . -name '*_integ_test.go' | xargs -I{} mv {} ../integtest)
@(cd $< && go build -v)
$(TARGETS_TEST): test-%:%
@(cd $< && go test -v)
$(TARGETS_CLEAN): clean-%:%
@echo "cleaning $<"
@-rm -rf $<
pre-doc:
@echo "Rendering doc server to ${DOC_SERVER_URL}"
find . -name \*.go |xargs sed -i '' 's/{{DOC_SERVER_URL}}/${DOC_SERVER_URL}/g'
gen-version:
go generate -x
release: gen-version build pre-doc

153
vendor/github.com/oracle/oci-go-sdk/README.md generated vendored Normal file
View File

@ -0,0 +1,153 @@
# Oracle Cloud Infrastructure Golang SDK
[![wercker status](https://app.wercker.com/status/09bc4818e7b1d70b04285331a9bdbc41/s/master "wercker status")](https://app.wercker.com/project/byKey/09bc4818e7b1d70b04285331a9bdbc41)
This is the Go SDK for Oracle Cloud Infrastructure. This project is open source and maintained by Oracle Corp.
The home page for the project is [here](https://godoc.org/github.com/oracle/oci-go-sdk/).
>***WARNING:***: To avoid automatically consuming breaking changes if we have to rev the major version of the Go SDK,
please consider using the [Go dependency management tool](https://github.com/golang/dep), or vendoring the SDK.
This will allow you to pin to a specific version of the Go SDK in your project, letting you control how and when you move to the next major version.
## Dependencies
- Install [Go programming language](https://golang.org/dl/).
- Install [GNU Make](https://www.gnu.org/software/make/), using the package manager or binary distribution tool appropriate for your platform.
## Installing
Use the following command to install this SDK:
```
go get -u github.com/oracle/oci-go-sdk
```
Alternatively you can git clone this repo.
## Working with the Go SDK
To start working with the Go SDK, you import the service package, create a client, and then use that client to make calls.
### Configuring
Before using the SDK, set up a config file with the required credentials. See [SDK and Tool Configuration](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) for instructions.
Once a config file has been setup, call `common.DefaultConfigProvider()` function as follows:
```go
// Import necessary packages
import (
"github.com/oracle/oci-go-sdk/common"
"github.com/oracle/oci-go-sdk/identity" // Identity or any other service you wish to make requests to
)
//...
configProvider := common.DefaultConfigProvider()
```
Or, to configure the SDK programmatically instead, implement the `ConfigurationProvider` interface shown below:
```go
// ConfigurationProvider wraps information about the account owner
type ConfigurationProvider interface {
KeyProvider
TenancyOCID() (string, error)
UserOCID() (string, error)
KeyFingerprint() (string, error)
Region() (string, error)
}
```
### Making a request
To make a request to an OCI service, create a client for the service and then use the client to call a function from the service.
- *Creating a client*: All packages provide a function to create clients, using the naming convention `New<ServiceName>ClientWithConfigurationProvider`,
such as `NewVirtualNetworkClientWithConfigurationProvider` or `NewIdentityClientWithConfigurationProvider`. To create a new client,
pass a struct that conforms to the `ConfigurationProvider` interface, or use the `DefaultConfigProvider()` function in the common package.
For example:
```go
config := common.DefaultConfigProvider()
client, err := identity.NewIdentityClientWithConfigurationProvider(config)
if err != nil {
panic(err)
}
```
- *Making calls*: After successfully creating a client, requests can now be made to the service. Generally all functions associated with an operation
accept [`context.Context`](https://golang.org/pkg/context/) and a struct that wraps all input parameters. The functions then return a response struct
that contains the desired data, and an error struct that describes the error if an error occurs.
For example:
```go
id := "your_group_id"
response, err := client.GetGroup(context.Background(), identity.GetGroupRequest{GroupId:&id})
if err != nil {
//Something happened
panic(err)
}
//Process the data in response struct
fmt.Println("Group's name is:", response.Name)
```
## Organization of the SDK
The `oci-go-sdk` contains the following:
- **Service packages**: All packages except `common` and any other package found inside `cmd`. These packages represent
the Oracle Cloud Infrastructure services supported by the Go SDK. Each package represents a service.
These packages include methods to interact with the service, structs that model
input and output parameters, and a client struct that acts as receiver for the above methods.
- **Common package**: Found in the `common` directory. The common package provides supporting functions and structs used by service packages.
Includes HTTP request/response (de)serialization, request signing, JSON parsing, pointer to reference and other helper functions. Most of the functions
in this package are meant to be used by the service packages.
- **cmd**: Internal tools used by the `oci-go-sdk`.
## Examples
Examples can be found [here](https://github.com/oracle/oci-go-sdk/tree/master/example)
## Documentation
Full documentation can be found [on the godocs site](https://godoc.org/github.com/oracle/oci-go-sdk/).
## Help
* The [Issues](https://github.com/oracle/oci-go-sdk/issues) page of this GitHub repository.
* [Stack Overflow](https://stackoverflow.com/), use the [oracle-cloud-infrastructure](https://stackoverflow.com/questions/tagged/oracle-cloud-infrastructure) and [oci-go-sdk](https://stackoverflow.com/questions/tagged/oci-go-sdk) tags in your post.
* [Developer Tools](https://community.oracle.com/community/cloud_computing/bare-metal/content?filterID=contentstatus%5Bpublished%5D~category%5Bdeveloper-tools%5D&filterID=contentstatus%5Bpublished%5D~objecttype~objecttype%5Bthread%5D) of the Oracle Cloud forums.
* [My Oracle Support](https://support.oracle.com).
## Contributing
`oci-go-sdk` is an open source project. See [CONTRIBUTING](/CONTRIBUTING.md) for details.
Oracle gratefully acknowledges the contributions to oci-go-sdk that have been made by the community.
## License
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
This SDK and sample is dual licensed under the Universal Permissive License 1.0 and the Apache License 2.0.
See [LICENSE](/LICENSE.txt) for more details.
## Changes
See [CHANGELOG](/CHANGELOG.md).
## Known Issues
You can find information on any known issues with the SDK here and under the [Issues](https://github.com/oracle/oci-go-sdk/issues) tab of this project's GitHub repository.
## Building and testing
### Dev dependencies
- Install [Testify](https://github.com/stretchr/testify) with the command:
```sh
go get github.com/stretchr/testify
```
- Install [go lint](https://github.com/golang/lint) with the command:
```
go get -u github.com/golang/lint/golint
```
### Build
Building is provided by the make file at the root of the project. To build the project execute.
```
make build
```
To run the tests:
```
make test
```

View File

@ -0,0 +1,113 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Audit API
//
// API for the Audit Service. You can use this API for queries, but not bulk-export operations.
//
package audit
import (
"context"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
//AuditClient a client for Audit
type AuditClient struct {
common.BaseClient
config *common.ConfigurationProvider
}
// NewAuditClientWithConfigurationProvider Creates a new default Audit client with the given configuration provider.
// the configuration provider will be used for the default signer as well as reading the region
func NewAuditClientWithConfigurationProvider(configProvider common.ConfigurationProvider) (client AuditClient, err error) {
baseClient, err := common.NewClientWithConfig(configProvider)
if err != nil {
return
}
client = AuditClient{BaseClient: baseClient}
client.BasePath = "20160918"
err = client.setConfigurationProvider(configProvider)
return
}
// SetRegion overrides the region of this client.
func (client *AuditClient) SetRegion(region string) {
client.Host = fmt.Sprintf(common.DefaultHostURLTemplate, "audit", region)
}
// SetConfigurationProvider sets the configuration provider including the region, returns an error if is not valid
func (client *AuditClient) setConfigurationProvider(configProvider common.ConfigurationProvider) error {
if ok, err := common.IsConfigurationProviderValid(configProvider); !ok {
return err
}
// Error has been checked already
region, _ := configProvider.Region()
client.config = &configProvider
client.SetRegion(region)
return nil
}
// ConfigurationProvider the ConfigurationProvider used in this client, or null if none set
func (client *AuditClient) ConfigurationProvider() *common.ConfigurationProvider {
return client.config
}
// GetConfiguration Get the configuration
func (client AuditClient) GetConfiguration(ctx context.Context, request GetConfigurationRequest) (response GetConfigurationResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/configuration", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListEvents Returns all audit events for the specified compartment that were processed within the specified time range.
func (client AuditClient) ListEvents(ctx context.Context, request ListEventsRequest) (response ListEventsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/auditEvents", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateConfiguration Update the configuration
func (client AuditClient) UpdateConfiguration(ctx context.Context, request UpdateConfigurationRequest) (response UpdateConfigurationResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/configuration", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}

View File

@ -0,0 +1,78 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Audit API
//
// API for the Audit Service. You can use this API for queries, but not bulk-export operations.
//
package audit
import (
"github.com/oracle/oci-go-sdk/common"
)
// AuditEvent The representation of AuditEvent
type AuditEvent struct {
// The OCID of the tenant.
TenantId *string `mandatory:"false" json:"tenantId"`
// The OCID of the compartment.
CompartmentId *string `mandatory:"false" json:"compartmentId"`
// The GUID of the event.
EventId *string `mandatory:"false" json:"eventId"`
// The source of the event.
EventSource *string `mandatory:"false" json:"eventSource"`
// The type of the event.
EventType *string `mandatory:"false" json:"eventType"`
// The time the event occurred, expressed in RFC 3339 (https://tools.ietf.org/html/rfc3339) timestamp format.
EventTime *common.SDKTime `mandatory:"false" json:"eventTime"`
// The OCID of the user whose action triggered the event.
PrincipalId *string `mandatory:"false" json:"principalId"`
// The credential ID of the user. This value is extracted from the HTTP 'Authorization' request header. It consists of the tenantId, userId, and user fingerprint, all delimited by a slash (/).
CredentialId *string `mandatory:"false" json:"credentialId"`
// The HTTP method of the request.
RequestAction *string `mandatory:"false" json:"requestAction"`
// The opc-request-id of the request.
RequestId *string `mandatory:"false" json:"requestId"`
// The user agent of the client that made the request.
RequestAgent *string `mandatory:"false" json:"requestAgent"`
// The HTTP header fields and values in the request.
RequestHeaders map[string][]string `mandatory:"false" json:"requestHeaders"`
// The IP address of the source of the request.
RequestOrigin *string `mandatory:"false" json:"requestOrigin"`
// The query parameter fields and values for the request.
RequestParameters map[string][]string `mandatory:"false" json:"requestParameters"`
// The resource targeted by the request.
RequestResource *string `mandatory:"false" json:"requestResource"`
// The headers of the response.
ResponseHeaders map[string][]string `mandatory:"false" json:"responseHeaders"`
// The status code of the response.
ResponseStatus *string `mandatory:"false" json:"responseStatus"`
// The time of the response to the audited request, expressed in RFC 3339 (https://tools.ietf.org/html/rfc3339) timestamp format.
ResponseTime *common.SDKTime `mandatory:"false" json:"responseTime"`
// Metadata of interest from the response payload. For example, the OCID of a resource.
ResponsePayload map[string]interface{} `mandatory:"false" json:"responsePayload"`
}
func (m AuditEvent) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Audit API
//
// API for the Audit Service. You can use this API for queries, but not bulk-export operations.
//
package audit
import (
"github.com/oracle/oci-go-sdk/common"
)
// Configuration The representation of Configuration
type Configuration struct {
// The retention period days
RetentionPeriodDays *int `mandatory:"false" json:"retentionPeriodDays"`
}
func (m Configuration) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package audit
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// GetConfigurationRequest wrapper for the GetConfiguration operation
type GetConfigurationRequest struct {
// ID of the root compartment (tenancy)
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
}
func (request GetConfigurationRequest) String() string {
return common.PointerString(request)
}
// GetConfigurationResponse wrapper for the GetConfiguration operation
type GetConfigurationResponse struct {
// The underlying http response
RawResponse *http.Response
// The Configuration instance
Configuration `presentIn:"body"`
}
func (response GetConfigurationResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,60 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package audit
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// ListEventsRequest wrapper for the ListEvents operation
type ListEventsRequest struct {
// The OCID of the compartment.
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
// Returns events that were processed at or after this start date and time, expressed in RFC 3339 (https://tools.ietf.org/html/rfc3339) timestamp format.
// For example, a start value of `2017-01-15T11:30:00Z` will retrieve a list of all events processed since 30 minutes after the 11th hour of January 15, 2017, in Coordinated Universal Time (UTC).
// You can specify a value with granularity to the minute. Seconds (and milliseconds, if included) must be set to `0`.
StartTime *common.SDKTime `mandatory:"true" contributesTo:"query" name:"startTime"`
// Returns events that were processed before this end date and time, expressed in RFC 3339 (https://tools.ietf.org/html/rfc3339) timestamp format. For example, a start value of `2017-01-01T00:00:00Z` and an end value of `2017-01-02T00:00:00Z` will retrieve a list of all events processed on January 1, 2017.
// Similarly, a start value of `2017-01-01T00:00:00Z` and an end value of `2017-02-01T00:00:00Z` will result in a list of all events processed between January 1, 2017 and January 31, 2017.
// You can specify a value with granularity to the minute. Seconds (and milliseconds, if included) must be set to `0`.
EndTime *common.SDKTime `mandatory:"true" contributesTo:"query" name:"endTime"`
// The value of the `opc-next-page` response header from the previous list query.
Page *string `mandatory:"false" contributesTo:"query" name:"page"`
// Unique Oracle-assigned identifier for the request.
// If you need to contact Oracle about a particular request, please provide the request ID.
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
}
func (request ListEventsRequest) String() string {
return common.PointerString(request)
}
// ListEventsResponse wrapper for the ListEvents operation
type ListEventsResponse struct {
// The underlying http response
RawResponse *http.Response
// The []AuditEvent instance
Items []AuditEvent `presentIn:"body"`
// For pagination of a list of audit events. When this header appears in the response,
// it means you received a partial list and there are more results.
// Include this value as the `page` parameter for the subsequent ListEvents request to get the next batch of events.
OpcNextPage *string `presentIn:"header" name:"opc-next-page"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response ListEventsResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Audit API
//
// API for the Audit Service. You can use this API for queries, but not bulk-export operations.
//
package audit
import (
"github.com/oracle/oci-go-sdk/common"
)
// UpdateConfigurationDetails The representation of UpdateConfigurationDetails
type UpdateConfigurationDetails struct {
// The retention period days
RetentionPeriodDays *int `mandatory:"false" json:"retentionPeriodDays"`
}
func (m UpdateConfigurationDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,41 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package audit
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// UpdateConfigurationRequest wrapper for the UpdateConfiguration operation
type UpdateConfigurationRequest struct {
// ID of the root compartment (tenancy)
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
// The configuration properties
UpdateConfigurationDetails `contributesTo:"body"`
}
func (request UpdateConfigurationRequest) String() string {
return common.PointerString(request)
}
// UpdateConfigurationResponse wrapper for the UpdateConfiguration operation
type UpdateConfigurationResponse struct {
// The underlying http response
RawResponse *http.Response
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
// particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
// The OCID (https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/identifiers.htm) of the work request.
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
}
func (response UpdateConfigurationResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,42 @@
package main
const versionTemplate = `
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated by go generate; DO NOT EDIT
package common
import (
"bytes"
"fmt"
"sync"
)
const (
major = "{{.Major}}"
minor = "{{.Minor}}"
patch = "{{.Patch}}"
tag = "{{.Tag}}"
)
var once sync.Once
var version string
// Version returns semantic version of the sdk
func Version() string {
once.Do(func() {
ver := fmt.Sprintf("%s.%s.%s", major, minor, patch)
verBuilder := bytes.NewBufferString(ver)
if tag != "" && tag != "-" {
_, err := verBuilder.WriteString(tag)
if err == nil {
verBuilder = bytes.NewBufferString(ver)
}
}
version = verBuilder.String()
})
return version
}
`

View File

@ -0,0 +1,154 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package auth
import (
"bytes"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"sync"
)
// x509CertificateRetriever provides an X509 certificate with the RSA private key
type x509CertificateRetriever interface {
Refresh() error
CertificatePemRaw() []byte
Certificate() *x509.Certificate
PrivateKeyPemRaw() []byte
PrivateKey() *rsa.PrivateKey
}
// urlBasedX509CertificateRetriever retrieves PEM-encoded X509 certificates from the given URLs.
type urlBasedX509CertificateRetriever struct {
certURL string
privateKeyURL string
passphrase string
certificatePemRaw []byte
certificate *x509.Certificate
privateKeyPemRaw []byte
privateKey *rsa.PrivateKey
mux sync.Mutex
}
func newURLBasedX509CertificateRetriever(certURL, privateKeyURL, passphrase string) x509CertificateRetriever {
return &urlBasedX509CertificateRetriever{
certURL: certURL,
privateKeyURL: privateKeyURL,
passphrase: passphrase,
mux: sync.Mutex{},
}
}
// Refresh() is failure atomic, i.e., CertificatePemRaw(), Certificate(), PrivateKeyPemRaw(), and PrivateKey() would
// return their previous values if Refresh() fails.
func (r *urlBasedX509CertificateRetriever) Refresh() error {
common.Debugln("Refreshing certificate")
r.mux.Lock()
defer r.mux.Unlock()
var err error
var certificatePemRaw []byte
var certificate *x509.Certificate
if certificatePemRaw, certificate, err = r.renewCertificate(r.certURL); err != nil {
return fmt.Errorf("failed to renew certificate: %s", err.Error())
}
var privateKeyPemRaw []byte
var privateKey *rsa.PrivateKey
if r.privateKeyURL != "" {
if privateKeyPemRaw, privateKey, err = r.renewPrivateKey(r.privateKeyURL, r.passphrase); err != nil {
return fmt.Errorf("failed to renew private key: %s", err.Error())
}
}
r.certificatePemRaw = certificatePemRaw
r.certificate = certificate
r.privateKeyPemRaw = privateKeyPemRaw
r.privateKey = privateKey
return nil
}
func (r *urlBasedX509CertificateRetriever) renewCertificate(url string) (certificatePemRaw []byte, certificate *x509.Certificate, err error) {
var body bytes.Buffer
if body, err = httpGet(url); err != nil {
return nil, nil, fmt.Errorf("failed to get certificate from %s: %s", url, err.Error())
}
certificatePemRaw = body.Bytes()
var block *pem.Block
block, _ = pem.Decode(certificatePemRaw)
if certificate, err = x509.ParseCertificate(block.Bytes); err != nil {
return nil, nil, fmt.Errorf("failed to parse the new certificate: %s", err.Error())
}
return certificatePemRaw, certificate, nil
}
func (r *urlBasedX509CertificateRetriever) renewPrivateKey(url, passphrase string) (privateKeyPemRaw []byte, privateKey *rsa.PrivateKey, err error) {
var body bytes.Buffer
if body, err = httpGet(url); err != nil {
return nil, nil, fmt.Errorf("failed to get private key from %s: %s", url, err.Error())
}
privateKeyPemRaw = body.Bytes()
if privateKey, err = common.PrivateKeyFromBytes(privateKeyPemRaw, &passphrase); err != nil {
return nil, nil, fmt.Errorf("failed to parse the new private key: %s", err.Error())
}
return privateKeyPemRaw, privateKey, nil
}
func (r *urlBasedX509CertificateRetriever) CertificatePemRaw() []byte {
r.mux.Lock()
defer r.mux.Unlock()
if r.certificatePemRaw == nil {
return nil
}
c := make([]byte, len(r.certificatePemRaw))
copy(c, r.certificatePemRaw)
return c
}
func (r *urlBasedX509CertificateRetriever) Certificate() *x509.Certificate {
r.mux.Lock()
defer r.mux.Unlock()
if r.certificate == nil {
return nil
}
c := *r.certificate
return &c
}
func (r *urlBasedX509CertificateRetriever) PrivateKeyPemRaw() []byte {
r.mux.Lock()
defer r.mux.Unlock()
if r.privateKeyPemRaw == nil {
return nil
}
c := make([]byte, len(r.privateKeyPemRaw))
copy(c, r.privateKeyPemRaw)
return c
}
func (r *urlBasedX509CertificateRetriever) PrivateKey() *rsa.PrivateKey {
r.mux.Lock()
defer r.mux.Unlock()
if r.privateKey == nil {
return nil
}
c := *r.privateKey
return &c
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package auth
import (
"crypto/rsa"
"fmt"
"github.com/oracle/oci-go-sdk/common"
)
type instancePrincipalConfigurationProvider struct {
keyProvider *instancePrincipalKeyProvider
region *common.Region
}
//InstancePrincipalConfigurationProvider returns a configuration for instance principals
func InstancePrincipalConfigurationProvider() (common.ConfigurationProvider, error) {
var err error
var keyProvider *instancePrincipalKeyProvider
if keyProvider, err = newInstancePrincipalKeyProvider(); err != nil {
return nil, fmt.Errorf("failed to create a new key provider for instance principal: %s", err.Error())
}
return instancePrincipalConfigurationProvider{keyProvider: keyProvider, region: nil}, nil
}
//InstancePrincipalConfigurationProviderForRegion returns a configuration for instance principals with a given region
func InstancePrincipalConfigurationProviderForRegion(region common.Region) (common.ConfigurationProvider, error) {
var err error
var keyProvider *instancePrincipalKeyProvider
if keyProvider, err = newInstancePrincipalKeyProvider(); err != nil {
return nil, fmt.Errorf("failed to create a new key provider for instance principal: %s", err.Error())
}
return instancePrincipalConfigurationProvider{keyProvider: keyProvider, region: &region}, nil
}
func (p instancePrincipalConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
return p.keyProvider.PrivateRSAKey()
}
func (p instancePrincipalConfigurationProvider) KeyID() (string, error) {
return p.keyProvider.KeyID()
}
func (p instancePrincipalConfigurationProvider) TenancyOCID() (string, error) {
return "", nil
}
func (p instancePrincipalConfigurationProvider) UserOCID() (string, error) {
return "", nil
}
func (p instancePrincipalConfigurationProvider) KeyFingerprint() (string, error) {
return "", nil
}
func (p instancePrincipalConfigurationProvider) Region() (string, error) {
if p.region == nil {
return string(p.keyProvider.RegionForFederationClient()), nil
}
return string(*p.region), nil
}

View File

@ -0,0 +1,288 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Package auth provides supporting functions and structs for authentication
package auth
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"net/http"
"strings"
"sync"
)
// federationClient is a client to retrieve the security token for an instance principal necessary to sign a request.
// It also provides the private key whose corresponding public key is used to retrieve the security token.
type federationClient interface {
PrivateKey() (*rsa.PrivateKey, error)
SecurityToken() (string, error)
}
// x509FederationClient retrieves a security token from Auth service.
type x509FederationClient struct {
tenancyID string
sessionKeySupplier sessionKeySupplier
leafCertificateRetriever x509CertificateRetriever
intermediateCertificateRetrievers []x509CertificateRetriever
securityToken securityToken
authClient *common.BaseClient
mux sync.Mutex
}
func newX509FederationClient(region common.Region, tenancyID string, leafCertificateRetriever x509CertificateRetriever, intermediateCertificateRetrievers []x509CertificateRetriever) federationClient {
client := &x509FederationClient{
tenancyID: tenancyID,
leafCertificateRetriever: leafCertificateRetriever,
intermediateCertificateRetrievers: intermediateCertificateRetrievers,
}
client.sessionKeySupplier = newSessionKeySupplier()
client.authClient = newAuthClient(region, client)
return client
}
var (
genericHeaders = []string{"date", "(request-target)"} // "host" is not needed for the federation endpoint. Don't ask me why.
bodyHeaders = []string{"content-length", "content-type", "x-content-sha256"}
)
func newAuthClient(region common.Region, provider common.KeyProvider) *common.BaseClient {
signer := common.RequestSigner(provider, genericHeaders, bodyHeaders)
client := common.DefaultBaseClientWithSigner(signer)
client.Host = fmt.Sprintf(common.DefaultHostURLTemplate, "auth", string(region))
client.BasePath = "v1/x509"
return &client
}
// For authClient to sign requests to X509 Federation Endpoint
func (c *x509FederationClient) KeyID() (string, error) {
tenancy := c.tenancyID
fingerprint := fingerprint(c.leafCertificateRetriever.Certificate())
return fmt.Sprintf("%s/fed-x509/%s", tenancy, fingerprint), nil
}
// For authClient to sign requests to X509 Federation Endpoint
func (c *x509FederationClient) PrivateRSAKey() (*rsa.PrivateKey, error) {
return c.leafCertificateRetriever.PrivateKey(), nil
}
func (c *x509FederationClient) PrivateKey() (*rsa.PrivateKey, error) {
c.mux.Lock()
defer c.mux.Unlock()
if err := c.renewSecurityTokenIfNotValid(); err != nil {
return nil, err
}
return c.sessionKeySupplier.PrivateKey(), nil
}
func (c *x509FederationClient) SecurityToken() (token string, err error) {
c.mux.Lock()
defer c.mux.Unlock()
if err = c.renewSecurityTokenIfNotValid(); err != nil {
return "", err
}
return c.securityToken.String(), nil
}
func (c *x509FederationClient) renewSecurityTokenIfNotValid() (err error) {
if c.securityToken == nil || !c.securityToken.Valid() {
if err = c.renewSecurityToken(); err != nil {
return fmt.Errorf("failed to renew security token: %s", err.Error())
}
}
return nil
}
func (c *x509FederationClient) renewSecurityToken() (err error) {
if err = c.sessionKeySupplier.Refresh(); err != nil {
return fmt.Errorf("failed to refresh session key: %s", err.Error())
}
if err = c.leafCertificateRetriever.Refresh(); err != nil {
return fmt.Errorf("failed to refresh leaf certificate: %s", err.Error())
}
updatedTenancyID := extractTenancyIDFromCertificate(c.leafCertificateRetriever.Certificate())
if c.tenancyID != updatedTenancyID {
err = fmt.Errorf("unexpected update of tenancy OCID in the leaf certificate. Previous tenancy: %s, Updated: %s", c.tenancyID, updatedTenancyID)
return
}
for _, retriever := range c.intermediateCertificateRetrievers {
if err = retriever.Refresh(); err != nil {
return fmt.Errorf("failed to refresh intermediate certificate: %s", err.Error())
}
}
if c.securityToken, err = c.getSecurityToken(); err != nil {
return fmt.Errorf("failed to get security token: %s", err.Error())
}
return nil
}
func (c *x509FederationClient) getSecurityToken() (securityToken, error) {
request := c.makeX509FederationRequest()
var err error
var httpRequest http.Request
if httpRequest, err = common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "", request); err != nil {
return nil, fmt.Errorf("failed to make http request: %s", err.Error())
}
var httpResponse *http.Response
defer common.CloseBodyIfValid(httpResponse)
if httpResponse, err = c.authClient.Call(context.Background(), &httpRequest); err != nil {
return nil, fmt.Errorf("failed to call: %s", err.Error())
}
response := x509FederationResponse{}
if err = common.UnmarshalResponse(httpResponse, &response); err != nil {
return nil, fmt.Errorf("failed to unmarshal the response: %s", err.Error())
}
return newInstancePrincipalToken(response.Token.Token)
}
type x509FederationRequest struct {
X509FederationDetails `contributesTo:"body"`
}
// X509FederationDetails x509 federation details
type X509FederationDetails struct {
Certificate string `mandatory:"true" json:"certificate,omitempty"`
PublicKey string `mandatory:"true" json:"publicKey,omitempty"`
IntermediateCertificates []string `mandatory:"false" json:"intermediateCertificates,omitempty"`
}
type x509FederationResponse struct {
Token `presentIn:"body"`
}
// Token token
type Token struct {
Token string `mandatory:"true" json:"token,omitempty"`
}
func (c *x509FederationClient) makeX509FederationRequest() *x509FederationRequest {
certificate := c.sanitizeCertificateString(string(c.leafCertificateRetriever.CertificatePemRaw()))
publicKey := c.sanitizeCertificateString(string(c.sessionKeySupplier.PublicKeyPemRaw()))
var intermediateCertificates []string
for _, retriever := range c.intermediateCertificateRetrievers {
intermediateCertificates = append(intermediateCertificates, c.sanitizeCertificateString(string(retriever.CertificatePemRaw())))
}
details := X509FederationDetails{
Certificate: certificate,
PublicKey: publicKey,
IntermediateCertificates: intermediateCertificates,
}
return &x509FederationRequest{details}
}
func (c *x509FederationClient) sanitizeCertificateString(certString string) string {
certString = strings.Replace(certString, "-----BEGIN CERTIFICATE-----", "", -1)
certString = strings.Replace(certString, "-----END CERTIFICATE-----", "", -1)
certString = strings.Replace(certString, "-----BEGIN PUBLIC KEY-----", "", -1)
certString = strings.Replace(certString, "-----END PUBLIC KEY-----", "", -1)
certString = strings.Replace(certString, "\n", "", -1)
return certString
}
// sessionKeySupplier provides an RSA keypair which can be re-generated by calling Refresh().
type sessionKeySupplier interface {
Refresh() error
PrivateKey() *rsa.PrivateKey
PublicKeyPemRaw() []byte
}
// inMemorySessionKeySupplier implements sessionKeySupplier to vend an RSA keypair.
// Refresh() generates a new RSA keypair with a random source, and keeps it in memory.
//
// inMemorySessionKeySupplier is not thread-safe.
type inMemorySessionKeySupplier struct {
keySize int
privateKey *rsa.PrivateKey
publicKeyPemRaw []byte
}
// newSessionKeySupplier creates and returns a sessionKeySupplier instance which generates key pairs of size 2048.
func newSessionKeySupplier() sessionKeySupplier {
return &inMemorySessionKeySupplier{keySize: 2048}
}
// Refresh() is failure atomic, i.e., PrivateKey() and PublicKeyPemRaw() would return their previous values
// if Refresh() fails.
func (s *inMemorySessionKeySupplier) Refresh() (err error) {
common.Debugln("Refreshing session key")
var privateKey *rsa.PrivateKey
privateKey, err = rsa.GenerateKey(rand.Reader, s.keySize)
if err != nil {
return fmt.Errorf("failed to generate a new keypair: %s", err)
}
var publicKeyAsnBytes []byte
if publicKeyAsnBytes, err = x509.MarshalPKIXPublicKey(privateKey.Public()); err != nil {
return fmt.Errorf("failed to marshal the public part of the new keypair: %s", err.Error())
}
publicKeyPemRaw := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyAsnBytes,
})
s.privateKey = privateKey
s.publicKeyPemRaw = publicKeyPemRaw
return nil
}
func (s *inMemorySessionKeySupplier) PrivateKey() *rsa.PrivateKey {
if s.privateKey == nil {
return nil
}
c := *s.privateKey
return &c
}
func (s *inMemorySessionKeySupplier) PublicKeyPemRaw() []byte {
if s.publicKeyPemRaw == nil {
return nil
}
c := make([]byte, len(s.publicKeyPemRaw))
copy(c, s.publicKeyPemRaw)
return c
}
type securityToken interface {
fmt.Stringer
Valid() bool
}
type instancePrincipalToken struct {
tokenString string
jwtToken *jwtToken
}
func newInstancePrincipalToken(tokenString string) (newToken securityToken, err error) {
var jwtToken *jwtToken
if jwtToken, err = parseJwt(tokenString); err != nil {
return nil, fmt.Errorf("failed to parse the token string \"%s\": %s", tokenString, err.Error())
}
return &instancePrincipalToken{tokenString, jwtToken}, nil
}
func (t *instancePrincipalToken) String() string {
return t.tokenString
}
func (t *instancePrincipalToken) Valid() bool {
return !t.jwtToken.expired()
}

View File

@ -0,0 +1,95 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package auth
import (
"bytes"
"crypto/rsa"
"fmt"
"github.com/oracle/oci-go-sdk/common"
)
const (
regionURL = `http://169.254.169.254/opc/v1/instance/region`
leafCertificateURL = `http://169.254.169.254/opc/v1/identity/cert.pem`
leafCertificateKeyURL = `http://169.254.169.254/opc/v1/identity/key.pem`
leafCertificateKeyPassphrase = `` // No passphrase for the private key for Compute instances
intermediateCertificateURL = `http://169.254.169.254/opc/v1/identity/intermediate.pem`
intermediateCertificateKeyURL = ``
intermediateCertificateKeyPassphrase = `` // No passphrase for the private key for Compute instances
)
// instancePrincipalKeyProvider implements KeyProvider to provide a key ID and its corresponding private key
// for an instance principal by getting a security token via x509FederationClient.
//
// The region name of the endpoint for x509FederationClient is obtained from the metadata service on the compute
// instance.
type instancePrincipalKeyProvider struct {
regionForFederationClient common.Region
federationClient federationClient
}
// newInstancePrincipalKeyProvider creates and returns an instancePrincipalKeyProvider instance based on
// x509FederationClient.
//
// NOTE: There is a race condition between PrivateRSAKey() and KeyID(). These two pieces are tightly coupled; KeyID
// includes a security token obtained from Auth service by giving a public key which is paired with PrivateRSAKey.
// The x509FederationClient caches the security token in memory until it is expired. Thus, even if a client obtains a
// KeyID that is not expired at the moment, the PrivateRSAKey that the client acquires at a next moment could be
// invalid because the KeyID could be already expired.
func newInstancePrincipalKeyProvider() (provider *instancePrincipalKeyProvider, err error) {
var region common.Region
if region, err = getRegionForFederationClient(regionURL); err != nil {
err = fmt.Errorf("failed to get the region name from %s: %s", regionURL, err.Error())
common.Logln(err)
return nil, err
}
leafCertificateRetriever := newURLBasedX509CertificateRetriever(
leafCertificateURL, leafCertificateKeyURL, leafCertificateKeyPassphrase)
intermediateCertificateRetrievers := []x509CertificateRetriever{
newURLBasedX509CertificateRetriever(
intermediateCertificateURL, intermediateCertificateKeyURL, intermediateCertificateKeyPassphrase),
}
if err = leafCertificateRetriever.Refresh(); err != nil {
err = fmt.Errorf("failed to refresh the leaf certificate: %s", err.Error())
return nil, err
}
tenancyID := extractTenancyIDFromCertificate(leafCertificateRetriever.Certificate())
federationClient := newX509FederationClient(
region, tenancyID, leafCertificateRetriever, intermediateCertificateRetrievers)
provider = &instancePrincipalKeyProvider{regionForFederationClient: region, federationClient: federationClient}
return
}
func getRegionForFederationClient(url string) (r common.Region, err error) {
var body bytes.Buffer
if body, err = httpGet(url); err != nil {
return
}
return common.StringToRegion(body.String()), nil
}
func (p *instancePrincipalKeyProvider) RegionForFederationClient() common.Region {
return p.regionForFederationClient
}
func (p *instancePrincipalKeyProvider) PrivateRSAKey() (privateKey *rsa.PrivateKey, err error) {
if privateKey, err = p.federationClient.PrivateKey(); err != nil {
err = fmt.Errorf("failed to get private key: %s", err.Error())
return nil, err
}
return privateKey, nil
}
func (p *instancePrincipalKeyProvider) KeyID() (string, error) {
var securityToken string
var err error
if securityToken, err = p.federationClient.SecurityToken(); err != nil {
return "", fmt.Errorf("failed to get security token: %s", err.Error())
}
return fmt.Sprintf("ST$%s", securityToken), nil
}

61
vendor/github.com/oracle/oci-go-sdk/common/auth/jwt.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package auth
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"
)
type jwtToken struct {
raw string
header map[string]interface{}
payload map[string]interface{}
}
func (t *jwtToken) expired() bool {
exp := int64(t.payload["exp"].(float64))
return exp <= time.Now().Unix()
}
func parseJwt(tokenString string) (*jwtToken, error) {
parts := strings.Split(tokenString, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("the given token string contains an invalid number of parts")
}
token := &jwtToken{raw: tokenString}
var err error
// Parse Header part
var headerBytes []byte
if headerBytes, err = decodePart(parts[0]); err != nil {
return nil, fmt.Errorf("failed to decode the header bytes: %s", err.Error())
}
if err = json.Unmarshal(headerBytes, &token.header); err != nil {
return nil, err
}
// Parse Payload part
var payloadBytes []byte
if payloadBytes, err = decodePart(parts[1]); err != nil {
return nil, fmt.Errorf("failed to decode the payload bytes: %s", err.Error())
}
decoder := json.NewDecoder(bytes.NewBuffer(payloadBytes))
if err = decoder.Decode(&token.payload); err != nil {
return nil, fmt.Errorf("failed to decode the payload json: %s", err.Error())
}
return token, nil
}
func decodePart(partString string) ([]byte, error) {
if l := len(partString) % 4; 0 < l {
partString += strings.Repeat("=", 4-l)
}
return base64.URLEncoding.DecodeString(partString)
}

View File

@ -0,0 +1,64 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package auth
import (
"bytes"
"crypto/sha1"
"crypto/x509"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"net/http"
"net/http/httputil"
"strings"
)
// httpGet makes a simple HTTP GET request to the given URL, expecting only "200 OK" status code.
// This is basically for the Instance Metadata Service.
func httpGet(url string) (body bytes.Buffer, err error) {
var response *http.Response
if response, err = http.Get(url); err != nil {
return
}
common.IfDebug(func() {
if dump, e := httputil.DumpResponse(response, true); e == nil {
common.Logf("Dump Response %v", string(dump))
} else {
common.Debugln(e)
}
})
defer response.Body.Close()
if _, err = body.ReadFrom(response.Body); err != nil {
return
}
if response.StatusCode != http.StatusOK {
err = fmt.Errorf("HTTP Get failed: URL: %s, Status: %s, Message: %s",
url, response.Status, body.String())
return
}
return
}
func extractTenancyIDFromCertificate(cert *x509.Certificate) string {
for _, nameAttr := range cert.Subject.Names {
value := nameAttr.Value.(string)
if strings.HasPrefix(value, "opc-tenant:") {
return value[len("opc-tenant:"):]
}
}
return ""
}
func fingerprint(certificate *x509.Certificate) string {
fingerprint := sha1.Sum(certificate.Raw)
return colonSeparatedString(fingerprint)
}
func colonSeparatedString(fingerprint [sha1.Size]byte) string {
spaceSeparated := fmt.Sprintf("% x", fingerprint)
return strings.Replace(spaceSeparated, " ", ":", -1)
}

253
vendor/github.com/oracle/oci-go-sdk/common/client.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Package common provides supporting functions and structs used by service packages
package common
import (
"context"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/user"
"path"
"runtime"
"strings"
"time"
)
const (
// DefaultHostURLTemplate The default url template for service hosts
DefaultHostURLTemplate = "%s.%s.oraclecloud.com"
defaultScheme = "https"
defaultSDKMarker = "Oracle-GoSDK"
defaultUserAgentTemplate = "%s/%s (%s/%s; go/%s)" //SDK/SDKVersion (OS/OSVersion; Lang/LangVersion)
defaultTimeout = time.Second * 30
defaultConfigFileName = "config"
defaultConfigDirName = ".oci"
secondaryConfigDirName = ".oraclebmc"
maxBodyLenForDebug = 1024 * 1000
)
// RequestInterceptor function used to customize the request before calling the underlying service
type RequestInterceptor func(*http.Request) error
// HTTPRequestDispatcher wraps the execution of a http request, it is generally implemented by
// http.Client.Do, but can be customized for testing
type HTTPRequestDispatcher interface {
Do(req *http.Request) (*http.Response, error)
}
// BaseClient struct implements all basic operations to call oci web services.
type BaseClient struct {
//HTTPClient performs the http network operations
HTTPClient HTTPRequestDispatcher
//Signer performs auth operation
Signer HTTPRequestSigner
//A request interceptor can be used to customize the request before signing and dispatching
Interceptor RequestInterceptor
//The host of the service
Host string
//The user agent
UserAgent string
//Base path for all operations of this client
BasePath string
}
func defaultUserAgent() string {
userAgent := fmt.Sprintf(defaultUserAgentTemplate, defaultSDKMarker, Version(), runtime.GOOS, runtime.GOARCH, runtime.Version())
return userAgent
}
func newBaseClient(signer HTTPRequestSigner, dispatcher HTTPRequestDispatcher) BaseClient {
return BaseClient{
UserAgent: defaultUserAgent(),
Interceptor: nil,
Signer: signer,
HTTPClient: dispatcher,
}
}
func defaultHTTPDispatcher() http.Client {
httpClient := http.Client{
Timeout: defaultTimeout,
}
return httpClient
}
func defaultBaseClient(provider KeyProvider) BaseClient {
dispatcher := defaultHTTPDispatcher()
signer := DefaultRequestSigner(provider)
return newBaseClient(signer, &dispatcher)
}
//DefaultBaseClientWithSigner creates a default base client with a given signer
func DefaultBaseClientWithSigner(signer HTTPRequestSigner) BaseClient {
dispatcher := defaultHTTPDispatcher()
return newBaseClient(signer, &dispatcher)
}
// NewClientWithConfig Create a new client with a configuration provider, the configuration provider
// will be used for the default signer as well as reading the region
// This function does not check for valid regions to implement forward compatibility
func NewClientWithConfig(configProvider ConfigurationProvider) (client BaseClient, err error) {
var ok bool
if ok, err = IsConfigurationProviderValid(configProvider); !ok {
err = fmt.Errorf("can not create client, bad configuration: %s", err.Error())
return
}
client = defaultBaseClient(configProvider)
return
}
func getHomeFolder() string {
current, e := user.Current()
if e != nil {
//Give up and try to return something sensible
home := os.Getenv("HOME")
if home == "" {
home = os.Getenv("USERPROFILE")
}
return home
}
return current.HomeDir
}
// DefaultConfigProvider returns the default config provider. The default config provider
// will look for configurations in 3 places: file in $HOME/.oci/config, HOME/.obmcs/config and
// variables names starting with the string TF_VAR. If the same configuration is found in multiple
// places the provider will prefer the first one.
func DefaultConfigProvider() ConfigurationProvider {
homeFolder := getHomeFolder()
defaultConfigFile := path.Join(homeFolder, defaultConfigDirName, defaultConfigFileName)
secondaryConfigFile := path.Join(homeFolder, secondaryConfigDirName, defaultConfigFileName)
defaultFileProvider, _ := ConfigurationProviderFromFile(defaultConfigFile, "")
secondaryFileProvider, _ := ConfigurationProviderFromFile(secondaryConfigFile, "")
environmentProvider := environmentConfigurationProvider{EnvironmentVariablePrefix: "TF_VAR"}
provider, _ := ComposingConfigurationProvider([]ConfigurationProvider{defaultFileProvider, secondaryFileProvider, environmentProvider})
Debugf("Configuration provided by: %s", provider)
return provider
}
func (client *BaseClient) prepareRequest(request *http.Request) (err error) {
if client.UserAgent == "" {
return fmt.Errorf("user agent can not be blank")
}
if request.Header == nil {
request.Header = http.Header{}
}
request.Header.Set("User-Agent", client.UserAgent)
if !strings.Contains(client.Host, "http") &&
!strings.Contains(client.Host, "https") {
client.Host = fmt.Sprintf("%s://%s", defaultScheme, client.Host)
}
clientURL, err := url.Parse(client.Host)
if err != nil {
return fmt.Errorf("host is invalid. %s", err.Error())
}
request.URL.Host = clientURL.Host
request.URL.Scheme = clientURL.Scheme
currentPath := request.URL.Path
request.URL.Path = path.Clean(fmt.Sprintf("/%s/%s", client.BasePath, currentPath))
return
}
func (client BaseClient) intercept(request *http.Request) (err error) {
if client.Interceptor != nil {
err = client.Interceptor(request)
}
return
}
func checkForSuccessfulResponse(res *http.Response) error {
familyStatusCode := res.StatusCode / 100
if familyStatusCode == 4 || familyStatusCode == 5 {
return newServiceFailureFromResponse(res)
}
return nil
}
//Call executes the underlying http requrest with the given context
func (client BaseClient) Call(ctx context.Context, request *http.Request) (response *http.Response, err error) {
Debugln("Atempting to call downstream service")
request = request.WithContext(ctx)
err = client.prepareRequest(request)
if err != nil {
return
}
//Intercept
err = client.intercept(request)
if err != nil {
return
}
//Sign the request
err = client.Signer.Sign(request)
if err != nil {
return
}
IfDebug(func() {
dumpBody := true
if request.ContentLength > maxBodyLenForDebug {
Logln("not dumping body too big")
dumpBody = false
}
if dump, e := httputil.DumpRequest(request, dumpBody); e == nil {
Logf("Dump Request %v", string(dump))
} else {
Debugln(e)
}
})
//Execute the http request
response, err = client.HTTPClient.Do(request)
IfDebug(func() {
if err != nil {
Logln(err)
return
}
dumpBody := true
if response.ContentLength > maxBodyLenForDebug {
Logln("not dumping body too big")
dumpBody = false
}
if dump, e := httputil.DumpResponse(response, dumpBody); e == nil {
Logf("Dump Response %v", string(dump))
} else {
Debugln(e)
}
})
if err != nil {
return
}
err = checkForSuccessfulResponse(response)
return
}
//CloseBodyIfValid closes the body of an http response if the response and the body are valid
func CloseBodyIfValid(httpResponse *http.Response) {
if httpResponse != nil && httpResponse.Body != nil {
httpResponse.Body.Close()
}
}

39
vendor/github.com/oracle/oci-go-sdk/common/common.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"strings"
)
//Region type for regions
type Region string
const (
//RegionSEA region SEA
RegionSEA Region = "sea"
//RegionPHX region PHX
RegionPHX Region = "us-phoenix-1"
//RegionIAD region IAD
RegionIAD Region = "us-ashburn-1"
//RegionFRA region FRA
RegionFRA Region = "eu-frankfurt-1"
)
//StringToRegion convert a string to Region type
func StringToRegion(stringRegion string) (r Region) {
switch strings.ToLower(stringRegion) {
case "sea":
r = RegionSEA
case "phx", "us-phoenix-1":
r = RegionPHX
case "iad", "us-ashburn-1":
r = RegionIAD
case "fra", "eu-frankfurt-1":
r = RegionFRA
default:
r = Region(stringRegion)
Debugf("region named: %s, is not recognized", stringRegion)
}
return
}

View File

@ -0,0 +1,487 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"crypto/rsa"
"errors"
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
)
// ConfigurationProvider wraps information about the account owner
type ConfigurationProvider interface {
KeyProvider
TenancyOCID() (string, error)
UserOCID() (string, error)
KeyFingerprint() (string, error)
Region() (string, error)
}
// IsConfigurationProviderValid Tests all parts of the configuration provider do not return an error
func IsConfigurationProviderValid(conf ConfigurationProvider) (ok bool, err error) {
baseFn := []func() (string, error){conf.TenancyOCID, conf.UserOCID, conf.KeyFingerprint, conf.Region, conf.KeyID}
for _, fn := range baseFn {
_, err = fn()
ok = err == nil
if err != nil {
return
}
}
_, err = conf.PrivateRSAKey()
ok = err == nil
if err != nil {
return
}
return true, nil
}
// rawConfigurationProvider allows a user to simply construct a configuration provider from raw values.
type rawConfigurationProvider struct {
tenancy string
user string
region string
fingerprint string
privateKey string
privateKeyPassphrase *string
}
// NewRawConfigurationProvider will create a rawConfigurationProvider
func NewRawConfigurationProvider(tenancy, user, region, fingerprint, privateKey string, privateKeyPassphrase *string) ConfigurationProvider {
return rawConfigurationProvider{tenancy, user, region, fingerprint, privateKey, privateKeyPassphrase}
}
func (p rawConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
return PrivateKeyFromBytes([]byte(p.privateKey), p.privateKeyPassphrase)
}
func (p rawConfigurationProvider) KeyID() (keyID string, err error) {
tenancy, err := p.TenancyOCID()
if err != nil {
return
}
user, err := p.UserOCID()
if err != nil {
return
}
fingerprint, err := p.KeyFingerprint()
if err != nil {
return
}
return fmt.Sprintf("%s/%s/%s", tenancy, user, fingerprint), nil
}
func (p rawConfigurationProvider) TenancyOCID() (string, error) {
return p.tenancy, nil
}
func (p rawConfigurationProvider) UserOCID() (string, error) {
return p.user, nil
}
func (p rawConfigurationProvider) KeyFingerprint() (string, error) {
return p.fingerprint, nil
}
func (p rawConfigurationProvider) Region() (string, error) {
return p.region, nil
}
// environmentConfigurationProvider reads configuration from environment variables
type environmentConfigurationProvider struct { // TODO: Support Instance Principal
PrivateKeyPassword string
EnvironmentVariablePrefix string
}
// ConfigurationProviderEnvironmentVariables creates a ConfigurationProvider from a uniform set of environment variables starting with a prefix
// The env variables should look like: [prefix]_private_key_path, [prefix]_tenancy_ocid, [prefix]_user_ocid, [prefix]_fingerprint
// [prefix]_region
func ConfigurationProviderEnvironmentVariables(environmentVariablePrefix, privateKeyPassword string) ConfigurationProvider {
return environmentConfigurationProvider{EnvironmentVariablePrefix: environmentVariablePrefix,
PrivateKeyPassword: privateKeyPassword}
}
func (p environmentConfigurationProvider) String() string {
return fmt.Sprintf("Configuration provided by environment variables prefixed with: %s", p.EnvironmentVariablePrefix)
}
func (p environmentConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "private_key_path")
var ok bool
var value string
if value, ok = os.LookupEnv(environmentVariable); !ok {
return nil, fmt.Errorf("can not read PrivateKey from env variable: %s", environmentVariable)
}
pemFileContent, err := ioutil.ReadFile(value)
if err != nil {
Debugln("Can not read PrivateKey location from environment variable: " + environmentVariable)
return
}
key, err = PrivateKeyFromBytes(pemFileContent, &p.PrivateKeyPassword)
return
}
func (p environmentConfigurationProvider) KeyID() (keyID string, err error) {
ocid, err := p.TenancyOCID()
if err != nil {
return
}
userocid, err := p.UserOCID()
if err != nil {
return
}
fingerprint, err := p.KeyFingerprint()
if err != nil {
return
}
return fmt.Sprintf("%s/%s/%s", ocid, userocid, fingerprint), nil
}
func (p environmentConfigurationProvider) TenancyOCID() (value string, err error) {
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "tenancy_ocid")
var ok bool
if value, ok = os.LookupEnv(environmentVariable); !ok {
err = fmt.Errorf("can not read Tenancy from environment variable %s", environmentVariable)
}
return
}
func (p environmentConfigurationProvider) UserOCID() (value string, err error) {
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "user_ocid")
var ok bool
if value, ok = os.LookupEnv(environmentVariable); !ok {
err = fmt.Errorf("can not read user id from environment variable %s", environmentVariable)
}
return
}
func (p environmentConfigurationProvider) KeyFingerprint() (value string, err error) {
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "fingerprint")
var ok bool
if value, ok = os.LookupEnv(environmentVariable); !ok {
err = fmt.Errorf("can not read fingerprint from environment variable %s", environmentVariable)
}
return
}
func (p environmentConfigurationProvider) Region() (value string, err error) {
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "region")
var ok bool
if value, ok = os.LookupEnv(environmentVariable); !ok {
err = fmt.Errorf("can not read region from environment variable %s", environmentVariable)
}
return
}
// fileConfigurationProvider. reads configuration information from a file
type fileConfigurationProvider struct { // TODO: Support Instance Principal
//The path to the configuration file
ConfigPath string
//The password for the private key
PrivateKeyPassword string
//The profile for the configuration
Profile string
//ConfigFileInfo
FileInfo *configFileInfo
}
// ConfigurationProviderFromFile creates a configuration provider from a configuration file
// by reading the "DEFAULT" profile
func ConfigurationProviderFromFile(configFilePath, privateKeyPassword string) (ConfigurationProvider, error) {
if configFilePath == "" {
return nil, fmt.Errorf("config file path can not be empty")
}
return fileConfigurationProvider{
ConfigPath: configFilePath,
PrivateKeyPassword: privateKeyPassword,
Profile: "DEFAULT"}, nil
}
// ConfigurationProviderFromFileWithProfile creates a configuration provider from a configuration file
// and the given profile
func ConfigurationProviderFromFileWithProfile(configFilePath, profile, privateKeyPassword string) (ConfigurationProvider, error) {
if configFilePath == "" {
return nil, fmt.Errorf("config file path can not be empty")
}
return fileConfigurationProvider{
ConfigPath: configFilePath,
PrivateKeyPassword: privateKeyPassword,
Profile: profile}, nil
}
type configFileInfo struct {
UserOcid, Fingerprint, KeyFilePath, TenancyOcid, Region string
PresentConfiguration byte
}
const (
hasTenancy = 1 << iota
hasUser
hasFingerprint
hasRegion
hasKeyFile
none
)
var profileRegex = regexp.MustCompile(`^\[(.*)\]`)
func parseConfigFile(data []byte, profile string) (info *configFileInfo, err error) {
if len(data) == 0 {
return nil, fmt.Errorf("configuration file content is empty")
}
content := string(data)
splitContent := strings.Split(content, "\n")
//Look for profile
for i, line := range splitContent {
if match := profileRegex.FindStringSubmatch(line); match != nil && len(match) > 1 && match[1] == profile {
start := i + 1
return parseConfigAtLine(start, splitContent)
}
}
return nil, fmt.Errorf("configuration file did not contain profile: %s", profile)
}
func parseConfigAtLine(start int, content []string) (info *configFileInfo, err error) {
var configurationPresent byte
info = &configFileInfo{}
for i := start; i < len(content); i++ {
line := content[i]
if profileRegex.MatchString(line) {
break
}
if !strings.Contains(line, "=") {
continue
}
splits := strings.Split(line, "=")
switch key, value := strings.TrimSpace(splits[0]), strings.TrimSpace(splits[1]); strings.ToLower(key) {
case "user":
configurationPresent = configurationPresent | hasUser
info.UserOcid = value
case "fingerprint":
configurationPresent = configurationPresent | hasFingerprint
info.Fingerprint = value
case "key_file":
configurationPresent = configurationPresent | hasKeyFile
info.KeyFilePath = value
case "tenancy":
configurationPresent = configurationPresent | hasTenancy
info.TenancyOcid = value
case "region":
configurationPresent = configurationPresent | hasRegion
info.Region = value
}
}
info.PresentConfiguration = configurationPresent
return
}
func openConfigFile(configFilePath string) (data []byte, err error) {
data, err = ioutil.ReadFile(configFilePath)
if err != nil {
err = fmt.Errorf("can not read config file: %s due to: %s", configFilePath, err.Error())
}
return
}
func (p fileConfigurationProvider) String() string {
return fmt.Sprintf("Configuration provided by file: %s", p.ConfigPath)
}
func (p fileConfigurationProvider) readAndParseConfigFile() (info *configFileInfo, err error) {
if p.FileInfo != nil {
return p.FileInfo, nil
}
if p.ConfigPath == "" {
return nil, fmt.Errorf("configuration path can not be empty")
}
data, err := openConfigFile(p.ConfigPath)
if err != nil {
err = fmt.Errorf("error while parsing config file: %s. Due to: %s", p.ConfigPath, err.Error())
return
}
p.FileInfo, err = parseConfigFile(data, p.Profile)
return p.FileInfo, err
}
func presentOrError(value string, expectedConf, presentConf byte, confMissing string) (string, error) {
if presentConf&expectedConf == expectedConf {
return value, nil
}
return "", errors.New(confMissing + " configuration is missing from file")
}
func (p fileConfigurationProvider) TenancyOCID() (value string, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
return
}
value, err = presentOrError(info.TenancyOcid, hasTenancy, info.PresentConfiguration, "tenancy")
return
}
func (p fileConfigurationProvider) UserOCID() (value string, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
return
}
value, err = presentOrError(info.UserOcid, hasUser, info.PresentConfiguration, "user")
return
}
func (p fileConfigurationProvider) KeyFingerprint() (value string, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
return
}
value, err = presentOrError(info.Fingerprint, hasFingerprint, info.PresentConfiguration, "fingerprint")
return
}
func (p fileConfigurationProvider) KeyID() (keyID string, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
return
}
return fmt.Sprintf("%s/%s/%s", info.TenancyOcid, info.UserOcid, info.Fingerprint), nil
}
func (p fileConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
return
}
filePath, err := presentOrError(info.KeyFilePath, hasKeyFile, info.PresentConfiguration, "key file path")
if err != nil {
return
}
pemFileContent, err := ioutil.ReadFile(filePath)
if err != nil {
err = fmt.Errorf("can not read PrivateKey from configuration file due to: %s", err.Error())
return
}
key, err = PrivateKeyFromBytes(pemFileContent, &p.PrivateKeyPassword)
return
}
func (p fileConfigurationProvider) Region() (value string, err error) {
info, err := p.readAndParseConfigFile()
if err != nil {
err = fmt.Errorf("can not read region configuration due to: %s", err.Error())
return
}
value, err = presentOrError(info.Region, hasRegion, info.PresentConfiguration, "region")
return
}
// A configuration provider that look for information in multiple configuration providers
type composingConfigurationProvider struct {
Providers []ConfigurationProvider
}
// ComposingConfigurationProvider creates a composing configuration provider with the given slice of configuration providers
// A composing provider will return the configuration of the first provider that has the required property
// if no provider has the property it will return an error.
func ComposingConfigurationProvider(providers []ConfigurationProvider) (ConfigurationProvider, error) {
if len(providers) == 0 {
return nil, fmt.Errorf("providers can not be an empty slice")
}
return composingConfigurationProvider{Providers: providers}, nil
}
func (c composingConfigurationProvider) TenancyOCID() (string, error) {
for _, p := range c.Providers {
val, err := p.TenancyOCID()
if err == nil {
return val, nil
}
}
return "", fmt.Errorf("did not find a proper configuration for tenancy")
}
func (c composingConfigurationProvider) UserOCID() (string, error) {
for _, p := range c.Providers {
val, err := p.UserOCID()
if err == nil {
return val, nil
}
}
return "", fmt.Errorf("did not find a proper configuration for user")
}
func (c composingConfigurationProvider) KeyFingerprint() (string, error) {
for _, p := range c.Providers {
val, err := p.KeyFingerprint()
if err == nil {
return val, nil
}
}
return "", fmt.Errorf("did not find a proper configuration for keyFingerprint")
}
func (c composingConfigurationProvider) Region() (string, error) {
for _, p := range c.Providers {
val, err := p.Region()
if err == nil {
return val, nil
}
}
return "", fmt.Errorf("did not find a proper configuration for region")
}
func (c composingConfigurationProvider) KeyID() (string, error) {
for _, p := range c.Providers {
val, err := p.KeyID()
if err == nil {
return val, nil
}
}
return "", fmt.Errorf("did not find a proper configuration for key id")
}
func (c composingConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
for _, p := range c.Providers {
val, err := p.PrivateRSAKey()
if err == nil {
return val, nil
}
}
return nil, fmt.Errorf("did not find a proper configuration for private key")
}

80
vendor/github.com/oracle/oci-go-sdk/common/errors.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
// ServiceError models all potential errors generated the service call
type ServiceError interface {
// The http status code of the error
GetHTTPStatusCode() int
// The human-readable error string as sent by the service
GetMessage() string
// A short error code that defines the error, meant for programmatic parsing.
// See https://docs.us-phoenix-1.oraclecloud.com/Content/API/References/apierrors.htm
GetCode() string
}
type servicefailure struct {
StatusCode int
Code string `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}
func newServiceFailureFromResponse(response *http.Response) error {
var err error
//If there is an error consume the body, entirely
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return servicefailure{
StatusCode: response.StatusCode,
Code: "BadErrorResponse",
Message: fmt.Sprintf("The body of the response was not readable, due to :%s", err.Error()),
}
}
se := servicefailure{StatusCode: response.StatusCode}
err = json.Unmarshal(body, &se)
if err != nil {
Debugf("Error response could not be parsed due to: %s", err.Error())
return servicefailure{
StatusCode: response.StatusCode,
Code: "BadErrorResponse",
Message: fmt.Sprintf("Error while parsing failure from response"),
}
}
return se
}
func (se servicefailure) Error() string {
return fmt.Sprintf("Service error:%s. %s. http status code: %d",
se.Code, se.Message, se.StatusCode)
}
func (se servicefailure) GetHTTPStatusCode() int {
return se.StatusCode
}
func (se servicefailure) GetMessage() string {
return se.Message
}
func (se servicefailure) GetCode() string {
return se.Code
}
// IsServiceError returns false if the error is not service side, otherwise true
// additionally it returns an interface representing the ServiceError
func IsServiceError(err error) (failure ServiceError, ok bool) {
failure, ok = err.(servicefailure)
return
}

168
vendor/github.com/oracle/oci-go-sdk/common/helpers.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"reflect"
"strings"
"time"
)
// String returns a pointer to the provided string
func String(value string) *string {
return &value
}
// Int returns a pointer to the provided int
func Int(value int) *int {
return &value
}
// Uint returns a pointer to the provided uint
func Uint(value uint) *uint {
return &value
}
//Float32 returns a pointer to the provided float32
func Float32(value float32) *float32 {
return &value
}
//Float64 returns a pointer to the provided float64
func Float64(value float64) *float64 {
return &value
}
//Bool returns a pointer to the provided bool
func Bool(value bool) *bool {
return &value
}
//PointerString prints the values of pointers in a struct
//Producing a human friendly string for an struct with pointers.
//useful when debugging the values of a struct
func PointerString(datastruct interface{}) (representation string) {
val := reflect.ValueOf(datastruct)
typ := reflect.TypeOf(datastruct)
all := make([]string, 2)
all = append(all, "{")
for i := 0; i < typ.NumField(); i++ {
sf := typ.Field(i)
//unexported
if sf.PkgPath != "" && !sf.Anonymous {
continue
}
sv := val.Field(i)
stringValue := ""
if isNil(sv) {
stringValue = fmt.Sprintf("%s=<nil>", sf.Name)
} else {
if sv.Type().Kind() == reflect.Ptr {
sv = sv.Elem()
}
stringValue = fmt.Sprintf("%s=%v", sf.Name, sv)
}
all = append(all, stringValue)
}
all = append(all, "}")
representation = strings.TrimSpace(strings.Join(all, " "))
return
}
// SDKTime a time struct, which renders to/from json using RFC339
type SDKTime struct {
time.Time
}
func sdkTimeFromTime(t time.Time) SDKTime {
return SDKTime{t}
}
func now() *SDKTime {
t := SDKTime{time.Now()}
return &t
}
var timeType = reflect.TypeOf(SDKTime{})
var timeTypePtr = reflect.TypeOf(&SDKTime{})
const sdkTimeFormat = time.RFC3339
const rfc1123OptionalLeadingDigitsInDay = "Mon, _2 Jan 2006 15:04:05 MST"
func formatTime(t SDKTime) string {
return t.Format(sdkTimeFormat)
}
func tryParsingTimeWithValidFormatsForHeaders(data []byte, headerName string) (t time.Time, err error) {
header := strings.ToLower(headerName)
switch header {
case "lastmodified", "date":
t, err = tryParsing(data, time.RFC3339, time.RFC1123, rfc1123OptionalLeadingDigitsInDay, time.RFC850, time.ANSIC)
return
default: //By default we parse with RFC3339
t, err = time.Parse(sdkTimeFormat, string(data))
return
}
}
func tryParsing(data []byte, layouts ...string) (tm time.Time, err error) {
datestring := string(data)
for _, l := range layouts {
tm, err = time.Parse(l, datestring)
if err == nil {
return
}
}
err = fmt.Errorf("Could not parse time: %s with formats: %s", datestring, layouts[:])
return
}
// UnmarshalJSON unmarshals from json
func (t *SDKTime) UnmarshalJSON(data []byte) (e error) {
s := string(data)
if s == "null" {
t.Time = time.Time{}
} else {
//Try parsing with RFC3339
t.Time, e = time.Parse(`"`+sdkTimeFormat+`"`, string(data))
}
return
}
// MarshalJSON marshals to JSON
func (t *SDKTime) MarshalJSON() (buff []byte, e error) {
s := t.Format(sdkTimeFormat)
buff = []byte(`"` + s + `"`)
return
}
// PrivateKeyFromBytes is a helper function that will produce a RSA private
// key from bytes.
func PrivateKeyFromBytes(pemData []byte, password *string) (key *rsa.PrivateKey, e error) {
if pemBlock, _ := pem.Decode(pemData); pemBlock != nil {
decrypted := pemBlock.Bytes
if x509.IsEncryptedPEMBlock(pemBlock) {
if password == nil {
e = fmt.Errorf("private_key_password is required for encrypted private keys")
return
}
if decrypted, e = x509.DecryptPEMBlock(pemBlock, []byte(*password)); e != nil {
return
}
}
key, e = x509.ParsePKCS1PrivateKey(decrypted)
} else {
e = fmt.Errorf("PEM data was not found in buffer")
return
}
return
}

863
vendor/github.com/oracle/oci-go-sdk/common/http.go generated vendored Normal file
View File

@ -0,0 +1,863 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"path"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Request Marshaling
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func isNil(v reflect.Value) bool {
return v.Kind() == reflect.Ptr && v.IsNil()
}
// Returns the string representation of a reflect.Value
// Only transforms primitive values
func toStringValue(v reflect.Value, field reflect.StructField) (string, error) {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return "", fmt.Errorf("can not marshal a nil pointer")
}
v = v.Elem()
}
if v.Type() == timeType {
t := v.Interface().(SDKTime)
return formatTime(t), nil
}
switch v.Kind() {
case reflect.Bool:
return strconv.FormatBool(v.Bool()), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10), nil
case reflect.String:
return v.String(), nil
case reflect.Float32:
return strconv.FormatFloat(v.Float(), 'f', 6, 32), nil
case reflect.Float64:
return strconv.FormatFloat(v.Float(), 'f', 6, 64), nil
default:
return "", fmt.Errorf("marshaling structure to a http.Request does not support field named: %s of type: %v",
field.Name, v.Type().String())
}
}
func addBinaryBody(request *http.Request, value reflect.Value) (e error) {
readCloser, ok := value.Interface().(io.ReadCloser)
if !ok {
e = fmt.Errorf("body of the request needs to be an io.ReadCloser interface. Can not marshal body of binary request")
return
}
request.Body = readCloser
//Set the default content type to application/octet-stream if not set
if request.Header.Get("Content-Type") == "" {
request.Header.Set("Content-Type", "application/octet-stream")
}
return nil
}
// getTaggedNilFieldNameOrError, evaluates if a field with json and non mandatory tags is nil
// returns the json tag name, or an error if the tags are incorrectly present
func getTaggedNilFieldNameOrError(field reflect.StructField, fieldValue reflect.Value) (bool, string, error) {
currentTag := field.Tag
jsonTag := currentTag.Get("json")
if jsonTag == "" {
return false, "", fmt.Errorf("json tag is not valid for field %s", field.Name)
}
partsJSONTag := strings.Split(jsonTag, ",")
nameJSONField := partsJSONTag[0]
if _, ok := currentTag.Lookup("mandatory"); !ok {
//No mandatory field set, no-op
return false, nameJSONField, nil
}
isMandatory, err := strconv.ParseBool(currentTag.Get("mandatory"))
if err != nil {
return false, "", fmt.Errorf("mandatory tag is not valid for field %s", field.Name)
}
// If the field is marked as mandatory, no-op
if isMandatory {
return false, nameJSONField, nil
}
Debugf("Adjusting tag: mandatory is false and json tag is valid on field: %s", field.Name)
// If the field can not be nil, then no-op
if !isNillableType(&fieldValue) {
Debugf("WARNING json field is tagged with mandatory flags, but the type can not be nil, field name: %s", field.Name)
return false, nameJSONField, nil
}
// If field value is nil, tag it as omitEmpty
return fieldValue.IsNil(), nameJSONField, nil
}
// isNillableType returns true if the filed can be nil
func isNillableType(value *reflect.Value) bool {
k := value.Kind()
switch k {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
return true
}
return false
}
// omitNilFieldsInJSON, removes json keys whose struct value is nil, and the field is tag with the json and
// mandatory:false tags
func omitNilFieldsInJSON(data interface{}, value reflect.Value) (interface{}, error) {
switch value.Kind() {
case reflect.Struct:
jsonMap := data.(map[string]interface{})
fieldType := value.Type()
for i := 0; i < fieldType.NumField(); i++ {
currentField := fieldType.Field(i)
//unexported skip
if currentField.PkgPath != "" {
continue
}
//Does not have json tag, no-op
if _, ok := currentField.Tag.Lookup("json"); !ok {
continue
}
currentFieldValue := value.Field(i)
ok, jsonFieldName, err := getTaggedNilFieldNameOrError(currentField, currentFieldValue)
if err != nil {
return nil, fmt.Errorf("can not omit nil fields for field: %s, due to: %s",
currentField.Name, err.Error())
}
//Delete the struct field from the json representation
if ok {
delete(jsonMap, jsonFieldName)
continue
}
if currentFieldValue.Type() == timeType || currentFieldValue.Type() == timeTypePtr {
continue
}
// does it need to be adjusted?
var adjustedValue interface{}
adjustedValue, err = omitNilFieldsInJSON(jsonMap[jsonFieldName], currentFieldValue)
if err != nil {
return nil, fmt.Errorf("can not omit nil fields for field: %s, due to: %s",
currentField.Name, err.Error())
}
jsonMap[jsonFieldName] = adjustedValue
}
return jsonMap, nil
case reflect.Slice, reflect.Array:
jsonList := data.([]interface{})
newList := make([]interface{}, len(jsonList))
var err error
for i, val := range jsonList {
newList[i], err = omitNilFieldsInJSON(val, value.Index(i))
if err != nil {
return nil, err
}
}
return newList, nil
case reflect.Map:
jsonMap := data.(map[string]interface{})
newMap := make(map[string]interface{}, len(jsonMap))
var err error
for key, val := range jsonMap {
newMap[key], err = omitNilFieldsInJSON(val, value.MapIndex(reflect.ValueOf(key)))
if err != nil {
return nil, err
}
}
return newMap, nil
case reflect.Ptr, reflect.Interface:
valPtr := value.Elem()
return omitNilFieldsInJSON(data, valPtr)
default:
//Otherwise no-op
return data, nil
}
}
// removeNilFieldsInJSONWithTaggedStruct remove struct fields tagged with json and mandatory false
// that are nil
func removeNilFieldsInJSONWithTaggedStruct(rawJSON []byte, value reflect.Value) ([]byte, error) {
rawMap := make(map[string]interface{})
json.Unmarshal(rawJSON, &rawMap)
fixedMap, err := omitNilFieldsInJSON(rawMap, value)
if err != nil {
return nil, err
}
return json.Marshal(fixedMap)
}
func addToBody(request *http.Request, value reflect.Value, field reflect.StructField) (e error) {
Debugln("Marshaling to body from field:", field.Name)
if request.Body != nil {
Logln("The body of the request is already set. Structure: ", field.Name, " will overwrite it")
}
tag := field.Tag
encoding := tag.Get("encoding")
if encoding == "binary" {
return addBinaryBody(request, value)
}
rawJSON, e := json.Marshal(value.Interface())
if e != nil {
return
}
marshaled, e := removeNilFieldsInJSONWithTaggedStruct(rawJSON, value)
if e != nil {
return
}
Debugf("Marshaled body is: %s", string(marshaled))
bodyBytes := bytes.NewReader(marshaled)
request.ContentLength = int64(bodyBytes.Len())
request.Header.Set("Content-Length", strconv.FormatInt(request.ContentLength, 10))
request.Header.Set("Content-Type", "application/json")
request.Body = ioutil.NopCloser(bodyBytes)
request.GetBody = func() (io.ReadCloser, error) {
return ioutil.NopCloser(bodyBytes), nil
}
return
}
func addToQuery(request *http.Request, value reflect.Value, field reflect.StructField) (e error) {
Debugln("Marshaling to query from field:", field.Name)
if request.URL == nil {
request.URL = &url.URL{}
}
query := request.URL.Query()
var queryParameterValue, queryParameterName string
if queryParameterName = field.Tag.Get("name"); queryParameterName == "" {
return fmt.Errorf("marshaling request to a query requires the 'name' tag for field: %s ", field.Name)
}
mandatory, _ := strconv.ParseBool(strings.ToLower(field.Tag.Get("mandatory")))
//If mandatory and nil. Error out
if mandatory && isNil(value) {
return fmt.Errorf("marshaling request to a header requires not nil pointer for field: %s", field.Name)
}
//if not mandatory and nil. Omit
if !mandatory && isNil(value) {
Debugf("Query parameter value is not mandatory and is nil pointer in field: %s. Skipping header", field.Name)
return
}
if queryParameterValue, e = toStringValue(value, field); e != nil {
return
}
//check for tag "omitEmpty", this is done to accomodate unset fields that do not
//support an empty string: enums in query params
if omitEmpty, present := field.Tag.Lookup("omitEmpty"); present {
omitEmptyBool, _ := strconv.ParseBool(strings.ToLower(omitEmpty))
if queryParameterValue != "" || !omitEmptyBool {
query.Set(queryParameterName, queryParameterValue)
} else {
Debugf("Omitting %s, is empty and omitEmpty tag is set", field.Name)
}
} else {
query.Set(queryParameterName, queryParameterValue)
}
request.URL.RawQuery = query.Encode()
return
}
// Adds to the path of the url in the order they appear in the structure
func addToPath(request *http.Request, value reflect.Value, field reflect.StructField) (e error) {
var additionalURLPathPart string
if additionalURLPathPart, e = toStringValue(value, field); e != nil {
return fmt.Errorf("can not marshal to path in request for field %s. Due to %s", field.Name, e.Error())
}
if request.URL == nil {
request.URL = &url.URL{}
request.URL.Path = ""
}
var currentURLPath = request.URL.Path
var templatedPathRegex, _ = regexp.Compile(".*{.+}.*")
if !templatedPathRegex.MatchString(currentURLPath) {
Debugln("Marshaling request to path by appending field:", field.Name)
allPath := []string{currentURLPath, additionalURLPathPart}
newPath := strings.Join(allPath, "/")
request.URL.Path = path.Clean(newPath)
} else {
var fieldName string
if fieldName = field.Tag.Get("name"); fieldName == "" {
e = fmt.Errorf("marshaling request to path name and template requires a 'name' tag for field: %s", field.Name)
return
}
urlTemplate := currentURLPath
Debugln("Marshaling to path from field:", field.Name, "in template:", urlTemplate)
request.URL.Path = path.Clean(strings.Replace(urlTemplate, "{"+fieldName+"}", additionalURLPathPart, -1))
}
return
}
func setWellKnownHeaders(request *http.Request, headerName, headerValue string) (e error) {
switch strings.ToLower(headerName) {
case "content-length":
var len int
len, e = strconv.Atoi(headerValue)
if e != nil {
return
}
request.ContentLength = int64(len)
}
return nil
}
func addToHeader(request *http.Request, value reflect.Value, field reflect.StructField) (e error) {
Debugln("Marshaling to header from field:", field.Name)
if request.Header == nil {
request.Header = http.Header{}
}
var headerName, headerValue string
if headerName = field.Tag.Get("name"); headerName == "" {
return fmt.Errorf("marshaling request to a header requires the 'name' tag for field: %s", field.Name)
}
mandatory, _ := strconv.ParseBool(strings.ToLower(field.Tag.Get("mandatory")))
//If mandatory and nil. Error out
if mandatory && isNil(value) {
return fmt.Errorf("marshaling request to a header requires not nil pointer for field: %s", field.Name)
}
//if not mandatory and nil. Omit
if !mandatory && isNil(value) {
Debugf("Header value is not mandatory and is nil pointer in field: %s. Skipping header", field.Name)
return
}
//Otherwise get value and set header
if headerValue, e = toStringValue(value, field); e != nil {
return
}
if e = setWellKnownHeaders(request, headerName, headerValue); e != nil {
return
}
request.Header.Set(headerName, headerValue)
return
}
// Header collection is a map of string to string that gets rendered as individual headers with a given prefix
func addToHeaderCollection(request *http.Request, value reflect.Value, field reflect.StructField) (e error) {
Debugln("Marshaling to header-collection from field:", field.Name)
if request.Header == nil {
request.Header = http.Header{}
}
var headerPrefix string
if headerPrefix = field.Tag.Get("prefix"); headerPrefix == "" {
return fmt.Errorf("marshaling request to a header requires the 'prefix' tag for field: %s", field.Name)
}
mandatory, _ := strconv.ParseBool(strings.ToLower(field.Tag.Get("mandatory")))
//If mandatory and nil. Error out
if mandatory && isNil(value) {
return fmt.Errorf("marshaling request to a header requires not nil pointer for field: %s", field.Name)
}
//if not mandatory and nil. Omit
if !mandatory && isNil(value) {
Debugf("Header value is not mandatory and is nil pointer in field: %s. Skipping header", field.Name)
return
}
//cast to map
headerValues, ok := value.Interface().(map[string]string)
if !ok {
e = fmt.Errorf("header fields need to be of type map[string]string")
return
}
for k, v := range headerValues {
headerName := fmt.Sprintf("%s%s", headerPrefix, k)
request.Header.Set(headerName, v)
}
return
}
// Makes sure the incoming structure is able to be marshalled
// to a request
func checkForValidRequestStruct(s interface{}) (*reflect.Value, error) {
val := reflect.ValueOf(s)
for val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil, fmt.Errorf("can not marshal to request a pointer to structure")
}
val = val.Elem()
}
if s == nil {
return nil, fmt.Errorf("can not marshal to request a nil structure")
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("can not marshal to request, expects struct input. Got %v", val.Kind())
}
return &val, nil
}
// Populates the parts of a request by reading tags in the passed structure
// nested structs are followed recursively depth-first.
func structToRequestPart(request *http.Request, val reflect.Value) (err error) {
typ := val.Type()
for i := 0; i < typ.NumField(); i++ {
if err != nil {
return
}
sf := typ.Field(i)
//unexported
if sf.PkgPath != "" && !sf.Anonymous {
continue
}
sv := val.Field(i)
tag := sf.Tag.Get("contributesTo")
switch tag {
case "header":
err = addToHeader(request, sv, sf)
case "header-collection":
err = addToHeaderCollection(request, sv, sf)
case "path":
err = addToPath(request, sv, sf)
case "query":
err = addToQuery(request, sv, sf)
case "body":
err = addToBody(request, sv, sf)
case "":
Debugln(sf.Name, "does not contain contributes tag. Skipping.")
default:
err = fmt.Errorf("can not marshal field: %s. It needs to contain valid contributesTo tag", sf.Name)
}
}
//If headers are and the content type was not set, we default to application/json
if request.Header != nil && request.Header.Get("Content-Type") == "" {
request.Header.Set("Content-Type", "application/json")
}
return
}
// HTTPRequestMarshaller marshals a structure to an http request using tag values in the struct
// The marshaller tag should like the following
// type A struct {
// ANumber string `contributesTo="query" name="number"`
// TheBody `contributesTo="body"`
// }
// where the contributesTo tag can be: header, path, query, body
// and the 'name' tag is the name of the value used in the http request(not applicable for path)
// If path is specified as part of the tag, the values are appened to the url path
// in the order they appear in the structure
// The current implementation only supports primitive types, except for the body tag, which needs a struct type.
// The body of a request will be marshaled using the tags of the structure
func HTTPRequestMarshaller(requestStruct interface{}, httpRequest *http.Request) (err error) {
var val *reflect.Value
if val, err = checkForValidRequestStruct(requestStruct); err != nil {
return
}
Debugln("Marshaling to Request:", val.Type().Name())
err = structToRequestPart(httpRequest, *val)
return
}
// MakeDefaultHTTPRequest creates the basic http request with the necessary headers set
func MakeDefaultHTTPRequest(method, path string) (httpRequest http.Request) {
httpRequest = http.Request{
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
Header: make(http.Header),
URL: &url.URL{},
}
httpRequest.Header.Set("Content-Length", "0")
httpRequest.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
httpRequest.Header.Set("Opc-Client-Info", strings.Join([]string{defaultSDKMarker, Version()}, "/"))
httpRequest.Header.Set("Accept", "*/*")
httpRequest.Method = method
httpRequest.URL.Path = path
return
}
// MakeDefaultHTTPRequestWithTaggedStruct creates an http request from an struct with tagged fields, see HTTPRequestMarshaller
// for more information
func MakeDefaultHTTPRequestWithTaggedStruct(method, path string, requestStruct interface{}) (httpRequest http.Request, err error) {
httpRequest = MakeDefaultHTTPRequest(method, path)
err = HTTPRequestMarshaller(requestStruct, &httpRequest)
return
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Request UnMarshaling
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Makes sure the incoming structure is able to be unmarshaled
// to a request
func checkForValidResponseStruct(s interface{}) (*reflect.Value, error) {
val := reflect.ValueOf(s)
for val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil, fmt.Errorf("can not unmarshal to response a pointer to nil structure")
}
val = val.Elem()
}
if s == nil {
return nil, fmt.Errorf("can not unmarshal to response a nil structure")
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("can not unmarshal to response, expects struct input. Got %v", val.Kind())
}
return &val, nil
}
func intSizeFromKind(kind reflect.Kind) int {
switch kind {
case reflect.Int8, reflect.Uint8:
return 8
case reflect.Int16, reflect.Uint16:
return 16
case reflect.Int32, reflect.Uint32:
return 32
case reflect.Int64, reflect.Uint64:
return 64
case reflect.Int, reflect.Uint:
return strconv.IntSize
default:
Debugln("The type is not valid: %v. Returing int size for arch", kind.String())
return strconv.IntSize
}
}
func analyzeValue(stringValue string, kind reflect.Kind, field reflect.StructField) (val reflect.Value, valPointer reflect.Value, err error) {
switch kind {
case timeType.Kind():
var t time.Time
t, err = tryParsingTimeWithValidFormatsForHeaders([]byte(stringValue), field.Name)
if err != nil {
return
}
sdkTime := sdkTimeFromTime(t)
val = reflect.ValueOf(sdkTime)
valPointer = reflect.ValueOf(&sdkTime)
return
case reflect.Bool:
var bVal bool
if bVal, err = strconv.ParseBool(stringValue); err != nil {
return
}
val = reflect.ValueOf(bVal)
valPointer = reflect.ValueOf(&bVal)
return
case reflect.Int:
size := intSizeFromKind(kind)
var iVal int64
if iVal, err = strconv.ParseInt(stringValue, 10, size); err != nil {
return
}
var iiVal int
iiVal = int(iVal)
val = reflect.ValueOf(iiVal)
valPointer = reflect.ValueOf(&iiVal)
return
case reflect.Int64:
size := intSizeFromKind(kind)
var iVal int64
if iVal, err = strconv.ParseInt(stringValue, 10, size); err != nil {
return
}
val = reflect.ValueOf(iVal)
valPointer = reflect.ValueOf(&iVal)
return
case reflect.Uint:
size := intSizeFromKind(kind)
var iVal uint64
if iVal, err = strconv.ParseUint(stringValue, 10, size); err != nil {
return
}
var uiVal uint
uiVal = uint(iVal)
val = reflect.ValueOf(uiVal)
valPointer = reflect.ValueOf(&uiVal)
return
case reflect.String:
val = reflect.ValueOf(stringValue)
valPointer = reflect.ValueOf(&stringValue)
case reflect.Float32:
var fVal float64
if fVal, err = strconv.ParseFloat(stringValue, 32); err != nil {
return
}
var ffVal float32
ffVal = float32(fVal)
val = reflect.ValueOf(ffVal)
valPointer = reflect.ValueOf(&ffVal)
return
case reflect.Float64:
var fVal float64
if fVal, err = strconv.ParseFloat(stringValue, 64); err != nil {
return
}
val = reflect.ValueOf(fVal)
valPointer = reflect.ValueOf(&fVal)
return
default:
err = fmt.Errorf("value for kind: %s not supported", kind)
}
return
}
// Sets the field of a struct, with the appropiate value of the string
// Only sets basic types
func fromStringValue(newValue string, val *reflect.Value, field reflect.StructField) (err error) {
if !val.CanSet() {
err = fmt.Errorf("can not set field name: %s of type: %v", field.Name, val.Type().String())
return
}
kind := val.Kind()
isPointer := false
if val.Kind() == reflect.Ptr {
isPointer = true
kind = field.Type.Elem().Kind()
}
value, valPtr, err := analyzeValue(newValue, kind, field)
if err != nil {
return
}
if !isPointer {
val.Set(value)
} else {
val.Set(valPtr)
}
return
}
// PolymorphicJSONUnmarshaler is the interface to unmarshal polymorphic json payloads
type PolymorphicJSONUnmarshaler interface {
UnmarshalPolymorphicJSON(data []byte) (interface{}, error)
}
func valueFromPolymorphicJSON(content []byte, unmarshaler PolymorphicJSONUnmarshaler) (val interface{}, err error) {
err = json.Unmarshal(content, unmarshaler)
if err != nil {
return
}
val, err = unmarshaler.UnmarshalPolymorphicJSON(content)
return
}
func valueFromJSONBody(response *http.Response, value *reflect.Value, unmarshaler PolymorphicJSONUnmarshaler) (val interface{}, err error) {
//Consumes the body, consider implementing it
//without body consumption
var content []byte
content, err = ioutil.ReadAll(response.Body)
if err != nil {
return
}
if unmarshaler != nil {
val, err = valueFromPolymorphicJSON(content, unmarshaler)
return
}
val = reflect.New(value.Type()).Interface()
err = json.Unmarshal(content, &val)
return
}
func addFromBody(response *http.Response, value *reflect.Value, field reflect.StructField, unmarshaler PolymorphicJSONUnmarshaler) (err error) {
Debugln("Unmarshaling from body to field:", field.Name)
if response.Body == nil {
Debugln("Unmarshaling body skipped due to nil body content for field: ", field.Name)
return nil
}
tag := field.Tag
encoding := tag.Get("encoding")
var iVal interface{}
switch encoding {
case "binary":
value.Set(reflect.ValueOf(response.Body))
return
case "plain-text":
//Expects UTF-8
byteArr, e := ioutil.ReadAll(response.Body)
if e != nil {
return e
}
str := string(byteArr)
value.Set(reflect.ValueOf(&str))
return
default: //If the encoding is not set. we'll decode with json
iVal, err = valueFromJSONBody(response, value, unmarshaler)
if err != nil {
return
}
newVal := reflect.ValueOf(iVal)
if newVal.Kind() == reflect.Ptr {
newVal = newVal.Elem()
}
value.Set(newVal)
return
}
}
func addFromHeader(response *http.Response, value *reflect.Value, field reflect.StructField) (err error) {
Debugln("Unmarshaling from header to field:", field.Name)
var headerName string
if headerName = field.Tag.Get("name"); headerName == "" {
return fmt.Errorf("unmarshaling response to a header requires the 'name' tag for field: %s", field.Name)
}
headerValue := response.Header.Get(headerName)
if headerValue == "" {
Debugf("Unmarshalling did not find header with name:%s", headerName)
return nil
}
if err = fromStringValue(headerValue, value, field); err != nil {
return fmt.Errorf("unmarshaling response to a header failed for field %s, due to %s", field.Name,
err.Error())
}
return
}
func addFromHeaderCollection(response *http.Response, value *reflect.Value, field reflect.StructField) error {
Debugln("Unmarshaling from header-collection to field:", field.Name)
var headerPrefix string
if headerPrefix = field.Tag.Get("prefix"); headerPrefix == "" {
return fmt.Errorf("Unmarshaling response to a header-collection requires the 'prefix' tag for field: %s", field.Name)
}
mapCollection := make(map[string]string)
for name, value := range response.Header {
nameLowerCase := strings.ToLower(name)
if strings.HasPrefix(nameLowerCase, headerPrefix) {
headerNoPrefix := strings.TrimPrefix(nameLowerCase, headerPrefix)
mapCollection[headerNoPrefix] = value[0]
}
}
Debugln("Marshalled header collection is:", mapCollection)
value.Set(reflect.ValueOf(mapCollection))
return nil
}
// Populates a struct from parts of a request by reading tags of the struct
func responseToStruct(response *http.Response, val *reflect.Value, unmarshaler PolymorphicJSONUnmarshaler) (err error) {
typ := val.Type()
for i := 0; i < typ.NumField(); i++ {
if err != nil {
return
}
sf := typ.Field(i)
//unexported
if sf.PkgPath != "" {
continue
}
sv := val.Field(i)
tag := sf.Tag.Get("presentIn")
switch tag {
case "header":
err = addFromHeader(response, &sv, sf)
case "header-collection":
err = addFromHeaderCollection(response, &sv, sf)
case "body":
err = addFromBody(response, &sv, sf, unmarshaler)
case "":
Debugln(sf.Name, "does not contain presentIn tag. Skipping")
default:
err = fmt.Errorf("can not unmarshal field: %s. It needs to contain valid presentIn tag", sf.Name)
}
}
return
}
// UnmarshalResponse hydrates the fields of a struct with the values of a http response, guided
// by the field tags. The directive tag is "presentIn" and it can be either
// - "header": Will look for the header tagged as "name" in the headers of the struct and set it value to that
// - "body": It will try to marshal the body from a json string to a struct tagged with 'presentIn: "body"'.
// Further this method will consume the body it should be safe to close it after this function
// Notice the current implementation only supports native types:int, strings, floats, bool as the field types
func UnmarshalResponse(httpResponse *http.Response, responseStruct interface{}) (err error) {
var val *reflect.Value
if val, err = checkForValidResponseStruct(responseStruct); err != nil {
return
}
if err = responseToStruct(httpResponse, val, nil); err != nil {
return
}
return nil
}
// UnmarshalResponseWithPolymorphicBody similar to UnmarshalResponse but assumes the body of the response
// contains polymorphic json. This function will use the unmarshaler argument to unmarshal json content
func UnmarshalResponseWithPolymorphicBody(httpResponse *http.Response, responseStruct interface{}, unmarshaler PolymorphicJSONUnmarshaler) (err error) {
var val *reflect.Value
if val, err = checkForValidResponseStruct(responseStruct); err != nil {
return
}
if err = responseToStruct(httpResponse, val, unmarshaler); err != nil {
return
}
return nil
}

View File

@ -0,0 +1,230 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
)
// HTTPRequestSigner the interface to sign a request
type HTTPRequestSigner interface {
Sign(r *http.Request) error
}
// KeyProvider interface that wraps information about the key's account owner
type KeyProvider interface {
PrivateRSAKey() (*rsa.PrivateKey, error)
KeyID() (string, error)
}
const signerVersion = "1"
// SignerBodyHashPredicate a function that allows to disable/enable body hashing
// of requests and headers associated with body content
type SignerBodyHashPredicate func(r *http.Request) bool
// ociRequestSigner implements the http-signatures-draft spec
// as described in https://tools.ietf.org/html/draft-cavage-http-signatures-08
type ociRequestSigner struct {
KeyProvider KeyProvider
GenericHeaders []string
BodyHeaders []string
ShouldHashBody SignerBodyHashPredicate
}
var (
defaultGenericHeaders = []string{"date", "(request-target)", "host"}
defaultBodyHeaders = []string{"content-length", "content-type", "x-content-sha256"}
defaultBodyHashPredicate = func(r *http.Request) bool {
return r.Method == http.MethodPost || r.Method == http.MethodPut
}
)
// DefaultRequestSigner creates a signer with default parameters.
func DefaultRequestSigner(provider KeyProvider) HTTPRequestSigner {
return RequestSigner(provider, defaultGenericHeaders, defaultBodyHeaders)
}
// RequestSigner creates a signer that utilizes the specified headers for signing
// and the default predicate for using the body of the request as part of the signature
func RequestSigner(provider KeyProvider, genericHeaders, bodyHeaders []string) HTTPRequestSigner {
return ociRequestSigner{
KeyProvider: provider,
GenericHeaders: genericHeaders,
BodyHeaders: bodyHeaders,
ShouldHashBody: defaultBodyHashPredicate}
}
// RequestSignerWithBodyHashingPredicate creates a signer that utilizes the specified headers for signing, as well as a predicate for using
// the body of the request and bodyHeaders parameter as part of the signature
func RequestSignerWithBodyHashingPredicate(provider KeyProvider, genericHeaders, bodyHeaders []string, shouldHashBody SignerBodyHashPredicate) HTTPRequestSigner {
return ociRequestSigner{
KeyProvider: provider,
GenericHeaders: genericHeaders,
BodyHeaders: bodyHeaders,
ShouldHashBody: shouldHashBody}
}
func (signer ociRequestSigner) getSigningHeaders(r *http.Request) []string {
var result []string
result = append(result, signer.GenericHeaders...)
if signer.ShouldHashBody(r) {
result = append(result, signer.BodyHeaders...)
}
return result
}
func (signer ociRequestSigner) getSigningString(request *http.Request) string {
signingHeaders := signer.getSigningHeaders(request)
signingParts := make([]string, len(signingHeaders))
for i, part := range signingHeaders {
var value string
switch part {
case "(request-target)":
value = getRequestTarget(request)
case "host":
value = request.URL.Host
if len(value) == 0 {
value = request.Host
}
default:
value = request.Header.Get(part)
}
signingParts[i] = fmt.Sprintf("%s: %s", part, value)
}
signingString := strings.Join(signingParts, "\n")
return signingString
}
func getRequestTarget(request *http.Request) string {
lowercaseMethod := strings.ToLower(request.Method)
return fmt.Sprintf("%s %s", lowercaseMethod, request.URL.RequestURI())
}
func calculateHashOfBody(request *http.Request) (err error) {
var hash string
if request.ContentLength > 0 {
hash, err = GetBodyHash(request)
if err != nil {
return
}
} else {
hash = hashAndEncode([]byte(""))
}
request.Header.Set("X-Content-Sha256", hash)
return
}
// drainBody reads all of b to memory and then returns two equivalent
// ReadClosers yielding the same bytes.
//
// It returns an error if the initial slurp of all bytes fails. It does not attempt
// to make the returned ReadClosers have identical error-matching behavior.
func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
if b == http.NoBody {
// No copying needed. Preserve the magic sentinel meaning of NoBody.
return http.NoBody, http.NoBody, nil
}
var buf bytes.Buffer
if _, err = buf.ReadFrom(b); err != nil {
return nil, b, err
}
if err = b.Close(); err != nil {
return nil, b, err
}
return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}
func hashAndEncode(data []byte) string {
hashedContent := sha256.Sum256(data)
hash := base64.StdEncoding.EncodeToString(hashedContent[:])
return hash
}
// GetBodyHash creates a base64 string from the hash of body the request
func GetBodyHash(request *http.Request) (hashString string, err error) {
if request.Body == nil {
return "", fmt.Errorf("can not read body of request while calculating body hash, nil body?")
}
var data []byte
bReader := request.Body
bReader, request.Body, err = drainBody(request.Body)
if err != nil {
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
}
data, err = ioutil.ReadAll(bReader)
if err != nil {
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
}
hashString = hashAndEncode(data)
return
}
func (signer ociRequestSigner) computeSignature(request *http.Request) (signature string, err error) {
signingString := signer.getSigningString(request)
hasher := sha256.New()
hasher.Write([]byte(signingString))
hashed := hasher.Sum(nil)
privateKey, err := signer.KeyProvider.PrivateRSAKey()
if err != nil {
return
}
var unencodedSig []byte
unencodedSig, e := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
if e != nil {
err = fmt.Errorf("can not compute signature while signing the request %s: ", e.Error())
return
}
signature = base64.StdEncoding.EncodeToString(unencodedSig)
return
}
// Sign signs the http request, by inspecting the necessary headers. Once signed
// the request will have the proper 'Authorization' header set, otherwise
// and error is returned
func (signer ociRequestSigner) Sign(request *http.Request) (err error) {
if signer.ShouldHashBody(request) {
err = calculateHashOfBody(request)
if err != nil {
return
}
}
var signature string
if signature, err = signer.computeSignature(request); err != nil {
return
}
signingHeaders := strings.Join(signer.getSigningHeaders(request), " ")
var keyID string
if keyID, err = signer.KeyProvider.KeyID(); err != nil {
return
}
authValue := fmt.Sprintf("Signature version=\"%s\",headers=\"%s\",keyId=\"%s\",algorithm=\"rsa-sha256\",signature=\"%s\"",
signerVersion, signingHeaders, keyID, signature)
request.Header.Set("Authorization", authValue)
return
}

67
vendor/github.com/oracle/oci-go-sdk/common/log.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
package common
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"sync"
)
// Simple logging proxy to distinguish control for logging messages
// Debug logging is turned on/off by the presence of the environment variable "OCI_GO_SDK_DEBUG"
var debugLog = log.New(os.Stderr, "DEBUG ", log.Ldate|log.Ltime|log.Lshortfile)
var mainLog = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
var isDebugLogEnabled bool
var checkDebug sync.Once
func getOutputForEnv() (writer io.Writer) {
checkDebug.Do(func() {
isDebugLogEnabled = *new(bool)
_, isDebugLogEnabled = os.LookupEnv("OCI_GO_SDK_DEBUG")
})
writer = ioutil.Discard
if isDebugLogEnabled {
writer = os.Stderr
}
return
}
// Debugf logs v with the provided format if debug mode is set
func Debugf(format string, v ...interface{}) {
debugLog.SetOutput(getOutputForEnv())
debugLog.Output(3, fmt.Sprintf(format, v...))
}
// Debug logs v if debug mode is set
func Debug(v ...interface{}) {
debugLog.SetOutput(getOutputForEnv())
debugLog.Output(3, fmt.Sprint(v...))
}
// Debugln logs v appending a new line if debug mode is set
func Debugln(v ...interface{}) {
debugLog.SetOutput(getOutputForEnv())
debugLog.Output(3, fmt.Sprintln(v...))
}
// IfDebug executes closure if debug is enabled
func IfDebug(fn func()) {
if isDebugLogEnabled {
fn()
}
}
// Logln logs v appending a new line at the end
func Logln(v ...interface{}) {
mainLog.Output(3, fmt.Sprintln(v...))
}
// Logf logs v with the provided format
func Logf(format string, v ...interface{}) {
mainLog.Output(3, fmt.Sprintf(format, v...))
}

36
vendor/github.com/oracle/oci-go-sdk/common/version.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated by go generate; DO NOT EDIT
package common
import (
"bytes"
"fmt"
"sync"
)
const (
major = "1"
minor = "0"
patch = "0"
tag = ""
)
var once sync.Once
var version string
// Version returns semantic version of the sdk
func Version() string {
once.Do(func() {
ver := fmt.Sprintf("%s.%s.%s", major, minor, patch)
verBuilder := bytes.NewBufferString(ver)
if tag != "" && tag != "-" {
_, err := verBuilder.WriteString(tag)
if err == nil {
verBuilder = bytes.NewBufferString(ver)
}
}
version = verBuilder.String()
})
return version
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// AttachBootVolumeDetails The representation of AttachBootVolumeDetails
type AttachBootVolumeDetails struct {
// The OCID of the boot volume.
BootVolumeId *string `mandatory:"true" json:"bootVolumeId"`
// The OCID of the instance.
InstanceId *string `mandatory:"true" json:"instanceId"`
// A user-friendly name. Does not have to be unique, and it cannot be changed. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m AttachBootVolumeDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// AttachBootVolumeRequest wrapper for the AttachBootVolume operation
type AttachBootVolumeRequest struct {
// Attach boot volume request
AttachBootVolumeDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request AttachBootVolumeRequest) String() string {
return common.PointerString(request)
}
// AttachBootVolumeResponse wrapper for the AttachBootVolume operation
type AttachBootVolumeResponse struct {
// The underlying http response
RawResponse *http.Response
// The BootVolumeAttachment instance
BootVolumeAttachment `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response AttachBootVolumeResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,63 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"encoding/json"
"github.com/oracle/oci-go-sdk/common"
)
// AttachIScsiVolumeDetails The representation of AttachIScsiVolumeDetails
type AttachIScsiVolumeDetails struct {
// The OCID of the instance.
InstanceId *string `mandatory:"true" json:"instanceId"`
// The OCID of the volume.
VolumeId *string `mandatory:"true" json:"volumeId"`
// A user-friendly name. Does not have to be unique, and it cannot be changed. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
// Whether to use CHAP authentication for the volume attachment. Defaults to false.
UseChap *bool `mandatory:"false" json:"useChap"`
}
//GetDisplayName returns DisplayName
func (m AttachIScsiVolumeDetails) GetDisplayName() *string {
return m.DisplayName
}
//GetInstanceId returns InstanceId
func (m AttachIScsiVolumeDetails) GetInstanceId() *string {
return m.InstanceId
}
//GetVolumeId returns VolumeId
func (m AttachIScsiVolumeDetails) GetVolumeId() *string {
return m.VolumeId
}
func (m AttachIScsiVolumeDetails) String() string {
return common.PointerString(m)
}
// MarshalJSON marshals to json representation
func (m AttachIScsiVolumeDetails) MarshalJSON() (buff []byte, e error) {
type MarshalTypeAttachIScsiVolumeDetails AttachIScsiVolumeDetails
s := struct {
DiscriminatorParam string `json:"type"`
MarshalTypeAttachIScsiVolumeDetails
}{
"iscsi",
(MarshalTypeAttachIScsiVolumeDetails)(m),
}
return json.Marshal(&s)
}

View File

@ -0,0 +1,37 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// AttachVnicDetails The representation of AttachVnicDetails
type AttachVnicDetails struct {
// Details for creating a new VNIC.
CreateVnicDetails *CreateVnicDetails `mandatory:"true" json:"createVnicDetails"`
// The OCID of the instance.
InstanceId *string `mandatory:"true" json:"instanceId"`
// A user-friendly name for the attachment. Does not have to be unique, and it cannot be changed.
DisplayName *string `mandatory:"false" json:"displayName"`
// Which physical network interface card (NIC) the VNIC will use. Defaults to 0.
// Certain bare metal instance shapes have two active physical NICs (0 and 1). If
// you add a secondary VNIC to one of these instances, you can specify which NIC
// the VNIC will use. For more information, see
// Virtual Network Interface Cards (VNICs) (https://docs.us-phoenix-1.oraclecloud.com/Content/Network/Tasks/managingVNICs.htm).
NicIndex *int `mandatory:"false" json:"nicIndex"`
}
func (m AttachVnicDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// AttachVnicRequest wrapper for the AttachVnic operation
type AttachVnicRequest struct {
// Attach VNIC details.
AttachVnicDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request AttachVnicRequest) String() string {
return common.PointerString(request)
}
// AttachVnicResponse wrapper for the AttachVnic operation
type AttachVnicResponse struct {
// The underlying http response
RawResponse *http.Response
// The VnicAttachment instance
VnicAttachment `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response AttachVnicResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"encoding/json"
"github.com/oracle/oci-go-sdk/common"
)
// AttachVolumeDetails The representation of AttachVolumeDetails
type AttachVolumeDetails interface {
// The OCID of the instance.
GetInstanceId() *string
// The OCID of the volume.
GetVolumeId() *string
// A user-friendly name. Does not have to be unique, and it cannot be changed. Avoid entering confidential information.
GetDisplayName() *string
}
type attachvolumedetails struct {
JsonData []byte
InstanceId *string `mandatory:"true" json:"instanceId"`
VolumeId *string `mandatory:"true" json:"volumeId"`
DisplayName *string `mandatory:"false" json:"displayName"`
Type string `json:"type"`
}
// UnmarshalJSON unmarshals json
func (m *attachvolumedetails) UnmarshalJSON(data []byte) error {
m.JsonData = data
type Unmarshalerattachvolumedetails attachvolumedetails
s := struct {
Model Unmarshalerattachvolumedetails
}{}
err := json.Unmarshal(data, &s.Model)
if err != nil {
return err
}
m.InstanceId = s.Model.InstanceId
m.VolumeId = s.Model.VolumeId
m.DisplayName = s.Model.DisplayName
m.Type = s.Model.Type
return err
}
// UnmarshalPolymorphicJSON unmarshals polymorphic json
func (m *attachvolumedetails) UnmarshalPolymorphicJSON(data []byte) (interface{}, error) {
var err error
switch m.Type {
case "iscsi":
mm := AttachIScsiVolumeDetails{}
err = json.Unmarshal(data, &mm)
return mm, err
default:
return m, nil
}
}
//GetInstanceId returns InstanceId
func (m attachvolumedetails) GetInstanceId() *string {
return m.InstanceId
}
//GetVolumeId returns VolumeId
func (m attachvolumedetails) GetVolumeId() *string {
return m.VolumeId
}
//GetDisplayName returns DisplayName
func (m attachvolumedetails) GetDisplayName() *string {
return m.DisplayName
}
func (m attachvolumedetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// AttachVolumeRequest wrapper for the AttachVolume operation
type AttachVolumeRequest struct {
// Attach volume request
AttachVolumeDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request AttachVolumeRequest) String() string {
return common.PointerString(request)
}
// AttachVolumeResponse wrapper for the AttachVolume operation
type AttachVolumeResponse struct {
// The underlying http response
RawResponse *http.Response
// The VolumeAttachment instance
VolumeAttachment `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response AttachVolumeResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// BootVolume A detachable boot volume device that contains the image used to boot an Compute instance. For more information, see
// Overview of Boot Volumes (https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Concepts/bootvolumes.htm).
// To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized,
// talk to an administrator. If you're an administrator who needs to write policies to give users access, see
// Getting Started with Policies (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/policygetstarted.htm).
type BootVolume struct {
// The Availability Domain of the boot volume.
// Example: `Uocm:PHX-AD-1`
AvailabilityDomain *string `mandatory:"true" json:"availabilityDomain"`
// The OCID of the compartment that contains the boot volume.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The boot volume's Oracle ID (OCID).
Id *string `mandatory:"true" json:"id"`
// The current state of a boot volume.
LifecycleState BootVolumeLifecycleStateEnum `mandatory:"true" json:"lifecycleState"`
// The size of the volume in MBs. The value must be a multiple of 1024.
// This field is deprecated. Please use sizeInGBs.
SizeInMBs *int `mandatory:"true" json:"sizeInMBs"`
// The date and time the boot volume was created. Format defined by RFC3339.
TimeCreated *common.SDKTime `mandatory:"true" json:"timeCreated"`
// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
// The image OCID used to create the boot volume.
ImageId *string `mandatory:"false" json:"imageId"`
// The size of the boot volume in GBs.
SizeInGBs *int `mandatory:"false" json:"sizeInGBs"`
}
func (m BootVolume) String() string {
return common.PointerString(m)
}
// BootVolumeLifecycleStateEnum Enum with underlying type: string
type BootVolumeLifecycleStateEnum string
// Set of constants representing the allowable values for BootVolumeLifecycleState
const (
BootVolumeLifecycleStateProvisioning BootVolumeLifecycleStateEnum = "PROVISIONING"
BootVolumeLifecycleStateRestoring BootVolumeLifecycleStateEnum = "RESTORING"
BootVolumeLifecycleStateAvailable BootVolumeLifecycleStateEnum = "AVAILABLE"
BootVolumeLifecycleStateTerminating BootVolumeLifecycleStateEnum = "TERMINATING"
BootVolumeLifecycleStateTerminated BootVolumeLifecycleStateEnum = "TERMINATED"
BootVolumeLifecycleStateFaulty BootVolumeLifecycleStateEnum = "FAULTY"
)
var mappingBootVolumeLifecycleState = map[string]BootVolumeLifecycleStateEnum{
"PROVISIONING": BootVolumeLifecycleStateProvisioning,
"RESTORING": BootVolumeLifecycleStateRestoring,
"AVAILABLE": BootVolumeLifecycleStateAvailable,
"TERMINATING": BootVolumeLifecycleStateTerminating,
"TERMINATED": BootVolumeLifecycleStateTerminated,
"FAULTY": BootVolumeLifecycleStateFaulty,
}
// GetBootVolumeLifecycleStateEnumValues Enumerates the set of values for BootVolumeLifecycleState
func GetBootVolumeLifecycleStateEnumValues() []BootVolumeLifecycleStateEnum {
values := make([]BootVolumeLifecycleStateEnum, 0)
for _, v := range mappingBootVolumeLifecycleState {
values = append(values, v)
}
return values
}

View File

@ -0,0 +1,76 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// BootVolumeAttachment Represents an attachment between a boot volume and an instance.
type BootVolumeAttachment struct {
// The Availability Domain of an instance.
// Example: `Uocm:PHX-AD-1`
AvailabilityDomain *string `mandatory:"true" json:"availabilityDomain"`
// The OCID of the boot volume.
BootVolumeId *string `mandatory:"true" json:"bootVolumeId"`
// The OCID of the compartment.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The OCID of the boot volume attachment.
Id *string `mandatory:"true" json:"id"`
// The OCID of the instance the boot volume is attached to.
InstanceId *string `mandatory:"true" json:"instanceId"`
// The current state of the boot volume attachment.
LifecycleState BootVolumeAttachmentLifecycleStateEnum `mandatory:"true" json:"lifecycleState"`
// The date and time the boot volume was created, in the format defined by RFC3339.
// Example: `2016-08-25T21:10:29.600Z`
TimeCreated *common.SDKTime `mandatory:"true" json:"timeCreated"`
// A user-friendly name. Does not have to be unique, and it cannot be changed.
// Avoid entering confidential information.
// Example: `My boot volume`
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m BootVolumeAttachment) String() string {
return common.PointerString(m)
}
// BootVolumeAttachmentLifecycleStateEnum Enum with underlying type: string
type BootVolumeAttachmentLifecycleStateEnum string
// Set of constants representing the allowable values for BootVolumeAttachmentLifecycleState
const (
BootVolumeAttachmentLifecycleStateAttaching BootVolumeAttachmentLifecycleStateEnum = "ATTACHING"
BootVolumeAttachmentLifecycleStateAttached BootVolumeAttachmentLifecycleStateEnum = "ATTACHED"
BootVolumeAttachmentLifecycleStateDetaching BootVolumeAttachmentLifecycleStateEnum = "DETACHING"
BootVolumeAttachmentLifecycleStateDetached BootVolumeAttachmentLifecycleStateEnum = "DETACHED"
)
var mappingBootVolumeAttachmentLifecycleState = map[string]BootVolumeAttachmentLifecycleStateEnum{
"ATTACHING": BootVolumeAttachmentLifecycleStateAttaching,
"ATTACHED": BootVolumeAttachmentLifecycleStateAttached,
"DETACHING": BootVolumeAttachmentLifecycleStateDetaching,
"DETACHED": BootVolumeAttachmentLifecycleStateDetached,
}
// GetBootVolumeAttachmentLifecycleStateEnumValues Enumerates the set of values for BootVolumeAttachmentLifecycleState
func GetBootVolumeAttachmentLifecycleStateEnumValues() []BootVolumeAttachmentLifecycleStateEnum {
values := make([]BootVolumeAttachmentLifecycleStateEnum, 0)
for _, v := range mappingBootVolumeAttachmentLifecycleState {
values = append(values, v)
}
return values
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// BulkAddVirtualCircuitPublicPrefixesDetails The representation of BulkAddVirtualCircuitPublicPrefixesDetails
type BulkAddVirtualCircuitPublicPrefixesDetails struct {
// The public IP prefixes (CIDRs) to add to the public virtual circuit.
PublicPrefixes []CreateVirtualCircuitPublicPrefixDetails `mandatory:"true" json:"publicPrefixes"`
}
func (m BulkAddVirtualCircuitPublicPrefixesDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// BulkAddVirtualCircuitPublicPrefixesRequest wrapper for the BulkAddVirtualCircuitPublicPrefixes operation
type BulkAddVirtualCircuitPublicPrefixesRequest struct {
// The OCID of the virtual circuit.
VirtualCircuitId *string `mandatory:"true" contributesTo:"path" name:"virtualCircuitId"`
// Request with publix prefixes to be added to the virtual circuit
BulkAddVirtualCircuitPublicPrefixesDetails `contributesTo:"body"`
}
func (request BulkAddVirtualCircuitPublicPrefixesRequest) String() string {
return common.PointerString(request)
}
// BulkAddVirtualCircuitPublicPrefixesResponse wrapper for the BulkAddVirtualCircuitPublicPrefixes operation
type BulkAddVirtualCircuitPublicPrefixesResponse struct {
// The underlying http response
RawResponse *http.Response
}
func (response BulkAddVirtualCircuitPublicPrefixesResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// BulkDeleteVirtualCircuitPublicPrefixesDetails The representation of BulkDeleteVirtualCircuitPublicPrefixesDetails
type BulkDeleteVirtualCircuitPublicPrefixesDetails struct {
// The public IP prefixes (CIDRs) to remove from the public virtual circuit.
PublicPrefixes []DeleteVirtualCircuitPublicPrefixDetails `mandatory:"true" json:"publicPrefixes"`
}
func (m BulkDeleteVirtualCircuitPublicPrefixesDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// BulkDeleteVirtualCircuitPublicPrefixesRequest wrapper for the BulkDeleteVirtualCircuitPublicPrefixes operation
type BulkDeleteVirtualCircuitPublicPrefixesRequest struct {
// The OCID of the virtual circuit.
VirtualCircuitId *string `mandatory:"true" contributesTo:"path" name:"virtualCircuitId"`
// Request with publix prefixes to be deleted from the virtual circuit
BulkDeleteVirtualCircuitPublicPrefixesDetails `contributesTo:"body"`
}
func (request BulkDeleteVirtualCircuitPublicPrefixesRequest) String() string {
return common.PointerString(request)
}
// BulkDeleteVirtualCircuitPublicPrefixesResponse wrapper for the BulkDeleteVirtualCircuitPublicPrefixes operation
type BulkDeleteVirtualCircuitPublicPrefixesResponse struct {
// The underlying http response
RawResponse *http.Response
}
func (response BulkDeleteVirtualCircuitPublicPrefixesResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CaptureConsoleHistoryDetails The representation of CaptureConsoleHistoryDetails
type CaptureConsoleHistoryDetails struct {
// The OCID of the instance to get the console history from.
InstanceId *string `mandatory:"true" json:"instanceId"`
// A user-friendly name. Does not have to be unique, and it's changeable.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CaptureConsoleHistoryDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CaptureConsoleHistoryRequest wrapper for the CaptureConsoleHistory operation
type CaptureConsoleHistoryRequest struct {
// Console history details
CaptureConsoleHistoryDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CaptureConsoleHistoryRequest) String() string {
return common.PointerString(request)
}
// CaptureConsoleHistoryResponse wrapper for the CaptureConsoleHistory operation
type CaptureConsoleHistoryResponse struct {
// The underlying http response
RawResponse *http.Response
// The ConsoleHistory instance
ConsoleHistory `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CaptureConsoleHistoryResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// ConnectLocalPeeringGatewaysDetails Information about the other local peering gateway (LPG).
type ConnectLocalPeeringGatewaysDetails struct {
// The OCID of the LPG you want to peer with.
PeerId *string `mandatory:"true" json:"peerId"`
}
func (m ConnectLocalPeeringGatewaysDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,38 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// ConnectLocalPeeringGatewaysRequest wrapper for the ConnectLocalPeeringGateways operation
type ConnectLocalPeeringGatewaysRequest struct {
// The OCID of the local peering gateway.
LocalPeeringGatewayId *string `mandatory:"true" contributesTo:"path" name:"localPeeringGatewayId"`
// Details regarding the local peering gateway to connect.
ConnectLocalPeeringGatewaysDetails `contributesTo:"body"`
}
func (request ConnectLocalPeeringGatewaysRequest) String() string {
return common.PointerString(request)
}
// ConnectLocalPeeringGatewaysResponse wrapper for the ConnectLocalPeeringGateways operation
type ConnectLocalPeeringGatewaysResponse struct {
// The underlying http response
RawResponse *http.Response
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response ConnectLocalPeeringGatewaysResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,75 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// ConsoleHistory An instance's serial console data. It includes configuration messages that occur when the
// instance boots, such as kernel and BIOS messages, and is useful for checking the status of
// the instance or diagnosing problems. The console data is minimally formatted ASCII text.
type ConsoleHistory struct {
// The Availability Domain of an instance.
// Example: `Uocm:PHX-AD-1`
AvailabilityDomain *string `mandatory:"true" json:"availabilityDomain"`
// The OCID of the compartment.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The OCID of the console history metadata object.
Id *string `mandatory:"true" json:"id"`
// The OCID of the instance this console history was fetched from.
InstanceId *string `mandatory:"true" json:"instanceId"`
// The current state of the console history.
LifecycleState ConsoleHistoryLifecycleStateEnum `mandatory:"true" json:"lifecycleState"`
// The date and time the history was created, in the format defined by RFC3339.
// Example: `2016-08-25T21:10:29.600Z`
TimeCreated *common.SDKTime `mandatory:"true" json:"timeCreated"`
// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
// Example: `My console history metadata`
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m ConsoleHistory) String() string {
return common.PointerString(m)
}
// ConsoleHistoryLifecycleStateEnum Enum with underlying type: string
type ConsoleHistoryLifecycleStateEnum string
// Set of constants representing the allowable values for ConsoleHistoryLifecycleState
const (
ConsoleHistoryLifecycleStateRequested ConsoleHistoryLifecycleStateEnum = "REQUESTED"
ConsoleHistoryLifecycleStateGettingHistory ConsoleHistoryLifecycleStateEnum = "GETTING-HISTORY"
ConsoleHistoryLifecycleStateSucceeded ConsoleHistoryLifecycleStateEnum = "SUCCEEDED"
ConsoleHistoryLifecycleStateFailed ConsoleHistoryLifecycleStateEnum = "FAILED"
)
var mappingConsoleHistoryLifecycleState = map[string]ConsoleHistoryLifecycleStateEnum{
"REQUESTED": ConsoleHistoryLifecycleStateRequested,
"GETTING-HISTORY": ConsoleHistoryLifecycleStateGettingHistory,
"SUCCEEDED": ConsoleHistoryLifecycleStateSucceeded,
"FAILED": ConsoleHistoryLifecycleStateFailed,
}
// GetConsoleHistoryLifecycleStateEnumValues Enumerates the set of values for ConsoleHistoryLifecycleState
func GetConsoleHistoryLifecycleStateEnumValues() []ConsoleHistoryLifecycleStateEnum {
values := make([]ConsoleHistoryLifecycleStateEnum, 0)
for _, v := range mappingConsoleHistoryLifecycleState {
values = append(values, v)
}
return values
}

View File

@ -0,0 +1,334 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"context"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
//BlockstorageClient a client for Blockstorage
type BlockstorageClient struct {
common.BaseClient
config *common.ConfigurationProvider
}
// NewBlockstorageClientWithConfigurationProvider Creates a new default Blockstorage client with the given configuration provider.
// the configuration provider will be used for the default signer as well as reading the region
func NewBlockstorageClientWithConfigurationProvider(configProvider common.ConfigurationProvider) (client BlockstorageClient, err error) {
baseClient, err := common.NewClientWithConfig(configProvider)
if err != nil {
return
}
client = BlockstorageClient{BaseClient: baseClient}
client.BasePath = "20160918"
err = client.setConfigurationProvider(configProvider)
return
}
// SetRegion overrides the region of this client.
func (client *BlockstorageClient) SetRegion(region string) {
client.Host = fmt.Sprintf(common.DefaultHostURLTemplate, "iaas", region)
}
// SetConfigurationProvider sets the configuration provider including the region, returns an error if is not valid
func (client *BlockstorageClient) setConfigurationProvider(configProvider common.ConfigurationProvider) error {
if ok, err := common.IsConfigurationProviderValid(configProvider); !ok {
return err
}
// Error has been checked already
region, _ := configProvider.Region()
client.config = &configProvider
client.SetRegion(region)
return nil
}
// ConfigurationProvider the ConfigurationProvider used in this client, or null if none set
func (client *BlockstorageClient) ConfigurationProvider() *common.ConfigurationProvider {
return client.config
}
// CreateVolume Creates a new volume in the specified compartment. Volumes can be created in sizes ranging from
// 50 GB (51200 MB) to 16 TB (16777216 MB), in 1 GB (1024 MB) increments. By default, volumes are 1 TB (1048576 MB).
// For general information about block volumes, see
// Overview of Block Volume Service (https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Concepts/overview.htm).
// A volume and instance can be in separate compartments but must be in the same Availability Domain.
// For information about access control and compartments, see
// Overview of the IAM Service (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/overview.htm). For information about
// Availability Domains, see Regions and Availability Domains (https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm).
// To get a list of Availability Domains, use the `ListAvailabilityDomains` operation
// in the Identity and Access Management Service API.
// You may optionally specify a *display name* for the volume, which is simply a friendly name or
// description. It does not have to be unique, and you can change it. Avoid entering confidential information.
func (client BlockstorageClient) CreateVolume(ctx context.Context, request CreateVolumeRequest) (response CreateVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/volumes", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// CreateVolumeBackup Creates a new backup of the specified volume. For general information about volume backups,
// see Overview of Block Volume Service Backups (https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Concepts/blockvolumebackups.htm)
// When the request is received, the backup object is in a REQUEST_RECEIVED state.
// When the data is imaged, it goes into a CREATING state.
// After the backup is fully uploaded to the cloud, it goes into an AVAILABLE state.
func (client BlockstorageClient) CreateVolumeBackup(ctx context.Context, request CreateVolumeBackupRequest) (response CreateVolumeBackupResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/volumeBackups", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteBootVolume Deletes the specified boot volume. The volume cannot have an active connection to an instance.
// To disconnect the boot volume from a connected instance, see
// Disconnecting From a Boot Volume (https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Tasks/deletingbootvolume.htm).
// **Warning:** All data on the boot volume will be permanently lost when the boot volume is deleted.
func (client BlockstorageClient) DeleteBootVolume(ctx context.Context, request DeleteBootVolumeRequest) (response DeleteBootVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/bootVolumes/{bootVolumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteVolume Deletes the specified volume. The volume cannot have an active connection to an instance.
// To disconnect the volume from a connected instance, see
// Disconnecting From a Volume (https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Tasks/disconnectingfromavolume.htm).
// **Warning:** All data on the volume will be permanently lost when the volume is deleted.
func (client BlockstorageClient) DeleteVolume(ctx context.Context, request DeleteVolumeRequest) (response DeleteVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/volumes/{volumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteVolumeBackup Deletes a volume backup.
func (client BlockstorageClient) DeleteVolumeBackup(ctx context.Context, request DeleteVolumeBackupRequest) (response DeleteVolumeBackupResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/volumeBackups/{volumeBackupId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetBootVolume Gets information for the specified boot volume.
func (client BlockstorageClient) GetBootVolume(ctx context.Context, request GetBootVolumeRequest) (response GetBootVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/bootVolumes/{bootVolumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetVolume Gets information for the specified volume.
func (client BlockstorageClient) GetVolume(ctx context.Context, request GetVolumeRequest) (response GetVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumes/{volumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetVolumeBackup Gets information for the specified volume backup.
func (client BlockstorageClient) GetVolumeBackup(ctx context.Context, request GetVolumeBackupRequest) (response GetVolumeBackupResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumeBackups/{volumeBackupId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListBootVolumes Lists the boot volumes in the specified compartment and Availability Domain.
func (client BlockstorageClient) ListBootVolumes(ctx context.Context, request ListBootVolumesRequest) (response ListBootVolumesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/bootVolumes", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListVolumeBackups Lists the volume backups in the specified compartment. You can filter the results by volume.
func (client BlockstorageClient) ListVolumeBackups(ctx context.Context, request ListVolumeBackupsRequest) (response ListVolumeBackupsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumeBackups", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListVolumes Lists the volumes in the specified compartment and Availability Domain.
func (client BlockstorageClient) ListVolumes(ctx context.Context, request ListVolumesRequest) (response ListVolumesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumes", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateBootVolume Updates the specified boot volume's display name.
func (client BlockstorageClient) UpdateBootVolume(ctx context.Context, request UpdateBootVolumeRequest) (response UpdateBootVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/bootVolumes/{bootVolumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateVolume Updates the specified volume's display name.
// Avoid entering confidential information.
func (client BlockstorageClient) UpdateVolume(ctx context.Context, request UpdateVolumeRequest) (response UpdateVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/volumes/{volumeId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateVolumeBackup Updates the display name for the specified volume backup.
// Avoid entering confidential information.
func (client BlockstorageClient) UpdateVolumeBackup(ctx context.Context, request UpdateVolumeBackupRequest) (response UpdateVolumeBackupResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/volumeBackups/{volumeBackupId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}

View File

@ -0,0 +1,833 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"context"
"fmt"
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
//ComputeClient a client for Compute
type ComputeClient struct {
common.BaseClient
config *common.ConfigurationProvider
}
// NewComputeClientWithConfigurationProvider Creates a new default Compute client with the given configuration provider.
// the configuration provider will be used for the default signer as well as reading the region
func NewComputeClientWithConfigurationProvider(configProvider common.ConfigurationProvider) (client ComputeClient, err error) {
baseClient, err := common.NewClientWithConfig(configProvider)
if err != nil {
return
}
client = ComputeClient{BaseClient: baseClient}
client.BasePath = "20160918"
err = client.setConfigurationProvider(configProvider)
return
}
// SetRegion overrides the region of this client.
func (client *ComputeClient) SetRegion(region string) {
client.Host = fmt.Sprintf(common.DefaultHostURLTemplate, "iaas", region)
}
// SetConfigurationProvider sets the configuration provider including the region, returns an error if is not valid
func (client *ComputeClient) setConfigurationProvider(configProvider common.ConfigurationProvider) error {
if ok, err := common.IsConfigurationProviderValid(configProvider); !ok {
return err
}
// Error has been checked already
region, _ := configProvider.Region()
client.config = &configProvider
client.SetRegion(region)
return nil
}
// ConfigurationProvider the ConfigurationProvider used in this client, or null if none set
func (client *ComputeClient) ConfigurationProvider() *common.ConfigurationProvider {
return client.config
}
// AttachBootVolume Attaches the specified boot volume to the specified instance.
func (client ComputeClient) AttachBootVolume(ctx context.Context, request AttachBootVolumeRequest) (response AttachBootVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/bootVolumeAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// AttachVnic Creates a secondary VNIC and attaches it to the specified instance.
// For more information about secondary VNICs, see
// Virtual Network Interface Cards (VNICs) (https://docs.us-phoenix-1.oraclecloud.com/Content/Network/Tasks/managingVNICs.htm).
func (client ComputeClient) AttachVnic(ctx context.Context, request AttachVnicRequest) (response AttachVnicResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/vnicAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// AttachVolume Attaches the specified storage volume to the specified instance.
func (client ComputeClient) AttachVolume(ctx context.Context, request AttachVolumeRequest) (response AttachVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/volumeAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponseWithPolymorphicBody(httpResponse, &response, &volumeattachment{})
return
}
// CaptureConsoleHistory Captures the most recent serial console data (up to a megabyte) for the
// specified instance.
// The `CaptureConsoleHistory` operation works with the other console history operations
// as described below.
// 1. Use `CaptureConsoleHistory` to request the capture of up to a megabyte of the
// most recent console history. This call returns a `ConsoleHistory`
// object. The object will have a state of REQUESTED.
// 2. Wait for the capture operation to succeed by polling `GetConsoleHistory` with
// the identifier of the console history metadata. The state of the
// `ConsoleHistory` object will go from REQUESTED to GETTING-HISTORY and
// then SUCCEEDED (or FAILED).
// 3. Use `GetConsoleHistoryContent` to get the actual console history data (not the
// metadata).
// 4. Optionally, use `DeleteConsoleHistory` to delete the console history metadata
// and the console history data.
func (client ComputeClient) CaptureConsoleHistory(ctx context.Context, request CaptureConsoleHistoryRequest) (response CaptureConsoleHistoryResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/instanceConsoleHistories/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// CreateImage Creates a boot disk image for the specified instance or imports an exported image from the Oracle Cloud Infrastructure Object Storage service.
// When creating a new image, you must provide the OCID of the instance you want to use as the basis for the image, and
// the OCID of the compartment containing that instance. For more information about images,
// see Managing Custom Images (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/managingcustomimages.htm).
// When importing an exported image from Object Storage, you specify the source information
// in ImageSourceDetails.
// When importing an image based on the namespace, bucket name, and object name,
// use ImageSourceViaObjectStorageTupleDetails.
// When importing an image based on the Object Storage URL, use
// ImageSourceViaObjectStorageUriDetails.
// See Object Storage URLs (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/imageimportexport.htm#URLs) and pre-authenticated requests (https://docs.us-phoenix-1.oraclecloud.com/Content/Object/Tasks/managingaccess.htm#pre-auth)
// for constructing URLs for image import/export.
// For more information about importing exported images, see
// Image Import/Export (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/imageimportexport.htm).
// You may optionally specify a *display name* for the image, which is simply a friendly name or description.
// It does not have to be unique, and you can change it. See UpdateImage.
// Avoid entering confidential information.
func (client ComputeClient) CreateImage(ctx context.Context, request CreateImageRequest) (response CreateImageResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/images/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// CreateInstanceConsoleConnection Creates a new console connection to the specified instance.
// Once the console connection has been created and is available,
// you connect to the console using SSH.
// For more information about console access, see Accessing the Console (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/References/serialconsole.htm).
func (client ComputeClient) CreateInstanceConsoleConnection(ctx context.Context, request CreateInstanceConsoleConnectionRequest) (response CreateInstanceConsoleConnectionResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/instanceConsoleConnections", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteConsoleHistory Deletes the specified console history metadata and the console history data.
func (client ComputeClient) DeleteConsoleHistory(ctx context.Context, request DeleteConsoleHistoryRequest) (response DeleteConsoleHistoryResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/instanceConsoleHistories/{instanceConsoleHistoryId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteImage Deletes an image.
func (client ComputeClient) DeleteImage(ctx context.Context, request DeleteImageRequest) (response DeleteImageResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/images/{imageId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DeleteInstanceConsoleConnection Deletes the specified instance console connection.
func (client ComputeClient) DeleteInstanceConsoleConnection(ctx context.Context, request DeleteInstanceConsoleConnectionRequest) (response DeleteInstanceConsoleConnectionResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/instanceConsoleConnections/{instanceConsoleConnectionId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DetachBootVolume Detaches a boot volume from an instance. You must specify the OCID of the boot volume attachment.
// This is an asynchronous operation. The attachment's `lifecycleState` will change to DETACHING temporarily
// until the attachment is completely removed.
func (client ComputeClient) DetachBootVolume(ctx context.Context, request DetachBootVolumeRequest) (response DetachBootVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/bootVolumeAttachments/{bootVolumeAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DetachVnic Detaches and deletes the specified secondary VNIC.
// This operation cannot be used on the instance's primary VNIC.
// When you terminate an instance, all attached VNICs (primary
// and secondary) are automatically detached and deleted.
// **Important:** If the VNIC has a
// PrivateIp that is the
// target of a route rule (https://docs.us-phoenix-1.oraclecloud.com/Content/Network/Tasks/managingroutetables.htm#privateip),
// deleting the VNIC causes that route rule to blackhole and the traffic
// will be dropped.
func (client ComputeClient) DetachVnic(ctx context.Context, request DetachVnicRequest) (response DetachVnicResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/vnicAttachments/{vnicAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// DetachVolume Detaches a storage volume from an instance. You must specify the OCID of the volume attachment.
// This is an asynchronous operation. The attachment's `lifecycleState` will change to DETACHING temporarily
// until the attachment is completely removed.
func (client ComputeClient) DetachVolume(ctx context.Context, request DetachVolumeRequest) (response DetachVolumeResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/volumeAttachments/{volumeAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ExportImage Exports the specified image to the Oracle Cloud Infrastructure Object Storage service. You can use the Object Storage URL,
// or the namespace, bucket name, and object name when specifying the location to export to.
// For more information about exporting images, see Image Import/Export (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/imageimportexport.htm).
// To perform an image export, you need write access to the Object Storage bucket for the image,
// see Let Users Write Objects to Object Storage Buckets (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/commonpolicies.htm#Let4).
// See Object Storage URLs (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/imageimportexport.htm#URLs) and pre-authenticated requests (https://docs.us-phoenix-1.oraclecloud.com/Content/Object/Tasks/managingaccess.htm#pre-auth)
// for constructing URLs for image import/export.
func (client ComputeClient) ExportImage(ctx context.Context, request ExportImageRequest) (response ExportImageResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/images/{imageId}/actions/export", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetBootVolumeAttachment Gets information about the specified boot volume attachment.
func (client ComputeClient) GetBootVolumeAttachment(ctx context.Context, request GetBootVolumeAttachmentRequest) (response GetBootVolumeAttachmentResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/bootVolumeAttachments/{bootVolumeAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetConsoleHistory Shows the metadata for the specified console history.
// See CaptureConsoleHistory
// for details about using the console history operations.
func (client ComputeClient) GetConsoleHistory(ctx context.Context, request GetConsoleHistoryRequest) (response GetConsoleHistoryResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instanceConsoleHistories/{instanceConsoleHistoryId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetConsoleHistoryContent Gets the actual console history data (not the metadata).
// See CaptureConsoleHistory
// for details about using the console history operations.
func (client ComputeClient) GetConsoleHistoryContent(ctx context.Context, request GetConsoleHistoryContentRequest) (response GetConsoleHistoryContentResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instanceConsoleHistories/{instanceConsoleHistoryId}/data", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetImage Gets the specified image.
func (client ComputeClient) GetImage(ctx context.Context, request GetImageRequest) (response GetImageResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/images/{imageId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetInstance Gets information about the specified instance.
func (client ComputeClient) GetInstance(ctx context.Context, request GetInstanceRequest) (response GetInstanceResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instances/{instanceId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetInstanceConsoleConnection Gets the specified instance console connection's information.
func (client ComputeClient) GetInstanceConsoleConnection(ctx context.Context, request GetInstanceConsoleConnectionRequest) (response GetInstanceConsoleConnectionResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instanceConsoleConnections/{instanceConsoleConnectionId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetVnicAttachment Gets the information for the specified VNIC attachment.
func (client ComputeClient) GetVnicAttachment(ctx context.Context, request GetVnicAttachmentRequest) (response GetVnicAttachmentResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/vnicAttachments/{vnicAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// GetVolumeAttachment Gets information about the specified volume attachment.
func (client ComputeClient) GetVolumeAttachment(ctx context.Context, request GetVolumeAttachmentRequest) (response GetVolumeAttachmentResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumeAttachments/{volumeAttachmentId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponseWithPolymorphicBody(httpResponse, &response, &volumeattachment{})
return
}
// GetWindowsInstanceInitialCredentials Gets the generated credentials for the instance. Only works for Windows instances. The returned credentials
// are only valid for the initial login.
func (client ComputeClient) GetWindowsInstanceInitialCredentials(ctx context.Context, request GetWindowsInstanceInitialCredentialsRequest) (response GetWindowsInstanceInitialCredentialsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instances/{instanceId}/initialCredentials", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// InstanceAction Performs one of the power actions (start, stop, softreset, or reset)
// on the specified instance.
// **start** - power on
// **stop** - power off
// **softreset** - ACPI shutdown and power on
// **reset** - power off and power on
// Note that the **stop** state has no effect on the resources you consume.
// Billing continues for instances that you stop, and related resources continue
// to apply against any relevant quotas. You must terminate an instance
// (TerminateInstance)
// to remove its resources from billing and quotas.
func (client ComputeClient) InstanceAction(ctx context.Context, request InstanceActionRequest) (response InstanceActionResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/instances/{instanceId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// LaunchInstance Creates a new instance in the specified compartment and the specified Availability Domain.
// For general information about instances, see
// Overview of the Compute Service (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Concepts/computeoverview.htm).
// For information about access control and compartments, see
// Overview of the IAM Service (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/overview.htm).
// For information about Availability Domains, see
// Regions and Availability Domains (https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm).
// To get a list of Availability Domains, use the `ListAvailabilityDomains` operation
// in the Identity and Access Management Service API.
// All Oracle Cloud Infrastructure resources, including instances, get an Oracle-assigned,
// unique ID called an Oracle Cloud Identifier (OCID).
// When you create a resource, you can find its OCID in the response. You can
// also retrieve a resource's OCID by using a List API operation
// on that resource type, or by viewing the resource in the Console.
// When you launch an instance, it is automatically attached to a virtual
// network interface card (VNIC), called the *primary VNIC*. The VNIC
// has a private IP address from the subnet's CIDR. You can either assign a
// private IP address of your choice or let Oracle automatically assign one.
// You can choose whether the instance has a public IP address. To retrieve the
// addresses, use the ListVnicAttachments
// operation to get the VNIC ID for the instance, and then call
// GetVnic with the VNIC ID.
// You can later add secondary VNICs to an instance. For more information, see
// Virtual Network Interface Cards (VNICs) (https://docs.us-phoenix-1.oraclecloud.com/Content/Network/Tasks/managingVNICs.htm).
func (client ComputeClient) LaunchInstance(ctx context.Context, request LaunchInstanceRequest) (response LaunchInstanceResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "/instances/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListBootVolumeAttachments Lists the boot volume attachments in the specified compartment. You can filter the
// list by specifying an instance OCID, boot volume OCID, or both.
func (client ComputeClient) ListBootVolumeAttachments(ctx context.Context, request ListBootVolumeAttachmentsRequest) (response ListBootVolumeAttachmentsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/bootVolumeAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListConsoleHistories Lists the console history metadata for the specified compartment or instance.
func (client ComputeClient) ListConsoleHistories(ctx context.Context, request ListConsoleHistoriesRequest) (response ListConsoleHistoriesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instanceConsoleHistories/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListImages Lists the available images in the specified compartment.
// If you specify a value for the `sortBy` parameter, Oracle-provided images appear first in the list, followed by custom images.
// For more
// information about images, see
// Managing Custom Images (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/Tasks/managingcustomimages.htm).
func (client ComputeClient) ListImages(ctx context.Context, request ListImagesRequest) (response ListImagesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/images/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListInstanceConsoleConnections Lists the console connections for the specified compartment or instance.
// For more information about console access, see Accessing the Instance Console (https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/References/serialconsole.htm).
func (client ComputeClient) ListInstanceConsoleConnections(ctx context.Context, request ListInstanceConsoleConnectionsRequest) (response ListInstanceConsoleConnectionsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instanceConsoleConnections", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListInstances Lists the instances in the specified compartment and the specified Availability Domain.
// You can filter the results by specifying an instance name (the list will include all the identically-named
// instances in the compartment).
func (client ComputeClient) ListInstances(ctx context.Context, request ListInstancesRequest) (response ListInstancesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/instances/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListShapes Lists the shapes that can be used to launch an instance within the specified compartment. You can
// filter the list by compatibility with a specific image.
func (client ComputeClient) ListShapes(ctx context.Context, request ListShapesRequest) (response ListShapesResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/shapes", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// ListVnicAttachments Lists the VNIC attachments in the specified compartment. A VNIC attachment
// resides in the same compartment as the attached instance. The list can be
// filtered by instance, VNIC, or Availability Domain.
func (client ComputeClient) ListVnicAttachments(ctx context.Context, request ListVnicAttachmentsRequest) (response ListVnicAttachmentsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/vnicAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
//listvolumeattachment allows to unmarshal list of polymorphic VolumeAttachment
type listvolumeattachment []volumeattachment
//UnmarshalPolymorphicJSON unmarshals polymorphic json list of items
func (m *listvolumeattachment) UnmarshalPolymorphicJSON(data []byte) (interface{}, error) {
res := make([]VolumeAttachment, len(*m))
for i, v := range *m {
nn, err := v.UnmarshalPolymorphicJSON(v.JsonData)
if err != nil {
return nil, err
}
res[i] = nn.(VolumeAttachment)
}
return res, nil
}
// ListVolumeAttachments Lists the volume attachments in the specified compartment. You can filter the
// list by specifying an instance OCID, volume OCID, or both.
// Currently, the only supported volume attachment type is IScsiVolumeAttachment.
func (client ComputeClient) ListVolumeAttachments(ctx context.Context, request ListVolumeAttachmentsRequest) (response ListVolumeAttachmentsResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, "/volumeAttachments/", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponseWithPolymorphicBody(httpResponse, &response, &listvolumeattachment{})
return
}
// TerminateInstance Terminates the specified instance. Any attached VNICs and volumes are automatically detached
// when the instance terminates.
// To preserve the boot volume associated with the instance, specify `true` for `PreserveBootVolumeQueryParam`.
// To delete the boot volume when the instance is deleted, specify `false` or do not specify a value for `PreserveBootVolumeQueryParam`.
// This is an asynchronous operation. The instance's `lifecycleState` will change to TERMINATING temporarily
// until the instance is completely removed.
func (client ComputeClient) TerminateInstance(ctx context.Context, request TerminateInstanceRequest) (response TerminateInstanceResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodDelete, "/instances/{instanceId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateConsoleHistory Updates the specified console history metadata.
func (client ComputeClient) UpdateConsoleHistory(ctx context.Context, request UpdateConsoleHistoryRequest) (response UpdateConsoleHistoryResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/instanceConsoleHistories/{instanceConsoleHistoryId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateImage Updates the display name of the image. Avoid entering confidential information.
func (client ComputeClient) UpdateImage(ctx context.Context, request UpdateImageRequest) (response UpdateImageResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/images/{imageId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}
// UpdateInstance Updates the display name of the specified instance. Avoid entering confidential information.
// The OCID of the instance remains the same.
func (client ComputeClient) UpdateInstance(ctx context.Context, request UpdateInstanceRequest) (response UpdateInstanceResponse, err error) {
httpRequest, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPut, "/instances/{instanceId}", request)
if err != nil {
return
}
httpResponse, err := client.Call(ctx, &httpRequest)
defer common.CloseBodyIfValid(httpResponse)
response.RawResponse = httpResponse
if err != nil {
return
}
err = common.UnmarshalResponse(httpResponse, &response)
return
}

File diff suppressed because it is too large Load Diff

45
vendor/github.com/oracle/oci-go-sdk/core/cpe.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// Cpe An object you create when setting up an IPSec VPN between your on-premises network
// and VCN. The `Cpe` is a virtual representation of your Customer-Premises Equipment,
// which is the actual router on-premises at your site at your end of the IPSec VPN connection.
// For more information,
// see Overview of the Networking Service (https://docs.us-phoenix-1.oraclecloud.com/Content/Network/Concepts/overview.htm).
// To use any of the API operations, you must be authorized in an IAM policy. If you're not authorized,
// talk to an administrator. If you're an administrator who needs to write policies to give users access, see
// Getting Started with Policies (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/policygetstarted.htm).
type Cpe struct {
// The OCID of the compartment containing the CPE.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The CPE's Oracle ID (OCID).
Id *string `mandatory:"true" json:"id"`
// The public IP address of the on-premises router.
IpAddress *string `mandatory:"true" json:"ipAddress"`
// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
// The date and time the CPE was created, in the format defined by RFC3339.
// Example: `2016-08-25T21:10:29.600Z`
TimeCreated *common.SDKTime `mandatory:"false" json:"timeCreated"`
}
func (m Cpe) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,31 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateCpeDetails The representation of CreateCpeDetails
type CreateCpeDetails struct {
// The OCID of the compartment to contain the CPE.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The public IP address of the on-premises router.
// Example: `143.19.23.16`
IpAddress *string `mandatory:"true" json:"ipAddress"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateCpeDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateCpeRequest wrapper for the CreateCpe operation
type CreateCpeRequest struct {
// Details for creating a CPE.
CreateCpeDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateCpeRequest) String() string {
return common.PointerString(request)
}
// CreateCpeResponse wrapper for the CreateCpe operation
type CreateCpeResponse struct {
// The underlying http response
RawResponse *http.Response
// The Cpe instance
Cpe `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateCpeResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,53 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateCrossConnectDetails The representation of CreateCrossConnectDetails
type CreateCrossConnectDetails struct {
// The OCID of the compartment to contain the cross-connect.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The name of the FastConnect location where this cross-connect will be installed.
// To get a list of the available locations, see
// ListCrossConnectLocations.
// Example: `CyrusOne, Chandler, AZ`
LocationName *string `mandatory:"true" json:"locationName"`
// The port speed for this cross-connect. To get a list of the available port speeds, see
// ListCrossconnectPortSpeedShapes.
// Example: `10 Gbps`
PortSpeedShapeName *string `mandatory:"true" json:"portSpeedShapeName"`
// The OCID of the cross-connect group to put this cross-connect in.
CrossConnectGroupId *string `mandatory:"false" json:"crossConnectGroupId"`
// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
// If you already have an existing cross-connect or cross-connect group at this FastConnect
// location, and you want this new cross-connect to be on a different router (for the
// purposes of redundancy), provide the OCID of that existing cross-connect or
// cross-connect group.
FarCrossConnectOrCrossConnectGroupId *string `mandatory:"false" json:"farCrossConnectOrCrossConnectGroupId"`
// If you already have an existing cross-connect or cross-connect group at this FastConnect
// location, and you want this new cross-connect to be on the same router, provide the
// OCID of that existing cross-connect or cross-connect group.
NearCrossConnectOrCrossConnectGroupId *string `mandatory:"false" json:"nearCrossConnectOrCrossConnectGroupId"`
}
func (m CreateCrossConnectDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,28 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateCrossConnectGroupDetails The representation of CreateCrossConnectGroupDetails
type CreateCrossConnectGroupDetails struct {
// The OCID of the compartment to contain the cross-connect group.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// A user-friendly name. Does not have to be unique, and it's changeable.
// Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateCrossConnectGroupDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateCrossConnectGroupRequest wrapper for the CreateCrossConnectGroup operation
type CreateCrossConnectGroupRequest struct {
// Details to create a CrossConnectGroup
CreateCrossConnectGroupDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateCrossConnectGroupRequest) String() string {
return common.PointerString(request)
}
// CreateCrossConnectGroupResponse wrapper for the CreateCrossConnectGroup operation
type CreateCrossConnectGroupResponse struct {
// The underlying http response
RawResponse *http.Response
// The CrossConnectGroup instance
CrossConnectGroup `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateCrossConnectGroupResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateCrossConnectRequest wrapper for the CreateCrossConnect operation
type CreateCrossConnectRequest struct {
// Details to create a CrossConnect
CreateCrossConnectDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateCrossConnectRequest) String() string {
return common.PointerString(request)
}
// CreateCrossConnectResponse wrapper for the CreateCrossConnect operation
type CreateCrossConnectResponse struct {
// The underlying http response
RawResponse *http.Response
// The CrossConnect instance
CrossConnect `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateCrossConnectResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"encoding/json"
"github.com/oracle/oci-go-sdk/common"
)
// CreateDhcpDetails The representation of CreateDhcpDetails
type CreateDhcpDetails struct {
// The OCID of the compartment to contain the set of DHCP options.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// A set of DHCP options.
Options []DhcpOption `mandatory:"true" json:"options"`
// The OCID of the VCN the set of DHCP options belongs to.
VcnId *string `mandatory:"true" json:"vcnId"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateDhcpDetails) String() string {
return common.PointerString(m)
}
// UnmarshalJSON unmarshals from json
func (m *CreateDhcpDetails) UnmarshalJSON(data []byte) (e error) {
model := struct {
DisplayName *string `json:"displayName"`
CompartmentId *string `json:"compartmentId"`
Options []dhcpoption `json:"options"`
VcnId *string `json:"vcnId"`
}{}
e = json.Unmarshal(data, &model)
if e != nil {
return
}
m.DisplayName = model.DisplayName
m.CompartmentId = model.CompartmentId
m.Options = make([]DhcpOption, len(model.Options))
for i, n := range model.Options {
nn, err := n.UnmarshalPolymorphicJSON(n.JsonData)
if err != nil {
return err
}
m.Options[i] = nn
}
m.VcnId = model.VcnId
return
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateDhcpOptionsRequest wrapper for the CreateDhcpOptions operation
type CreateDhcpOptionsRequest struct {
// Request object for creating a new set of DHCP options.
CreateDhcpDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateDhcpOptionsRequest) String() string {
return common.PointerString(request)
}
// CreateDhcpOptionsResponse wrapper for the CreateDhcpOptions operation
type CreateDhcpOptionsResponse struct {
// The underlying http response
RawResponse *http.Response
// The DhcpOptions instance
DhcpOptions `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateDhcpOptionsResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateDrgAttachmentDetails The representation of CreateDrgAttachmentDetails
type CreateDrgAttachmentDetails struct {
// The OCID of the DRG.
DrgId *string `mandatory:"true" json:"drgId"`
// The OCID of the VCN.
VcnId *string `mandatory:"true" json:"vcnId"`
// A user-friendly name. Does not have to be unique. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateDrgAttachmentDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateDrgAttachmentRequest wrapper for the CreateDrgAttachment operation
type CreateDrgAttachmentRequest struct {
// Details for creating a `DrgAttachment`.
CreateDrgAttachmentDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateDrgAttachmentRequest) String() string {
return common.PointerString(request)
}
// CreateDrgAttachmentResponse wrapper for the CreateDrgAttachment operation
type CreateDrgAttachmentResponse struct {
// The underlying http response
RawResponse *http.Response
// The DrgAttachment instance
DrgAttachment `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateDrgAttachmentResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateDrgDetails The representation of CreateDrgDetails
type CreateDrgDetails struct {
// The OCID of the compartment to contain the DRG.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateDrgDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateDrgRequest wrapper for the CreateDrg operation
type CreateDrgRequest struct {
// Details for creating a DRG.
CreateDrgDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateDrgRequest) String() string {
return common.PointerString(request)
}
// CreateDrgResponse wrapper for the CreateDrg operation
type CreateDrgResponse struct {
// The underlying http response
RawResponse *http.Response
// The Drg instance
Drg `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateDrgResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateIPSecConnectionRequest wrapper for the CreateIPSecConnection operation
type CreateIPSecConnectionRequest struct {
// Details for creating an `IPSecConnection`.
CreateIpSecConnectionDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateIPSecConnectionRequest) String() string {
return common.PointerString(request)
}
// CreateIPSecConnectionResponse wrapper for the CreateIPSecConnection operation
type CreateIPSecConnectionResponse struct {
// The underlying http response
RawResponse *http.Response
// The IpSecConnection instance
IpSecConnection `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateIPSecConnectionResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"encoding/json"
"github.com/oracle/oci-go-sdk/common"
)
// CreateImageDetails Either instanceId or imageSourceDetails must be provided in addition to other required parameters.
type CreateImageDetails struct {
// The OCID of the compartment containing the instance you want to use as the basis for the image.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// A user-friendly name for the image. It does not have to be unique, and it's changeable.
// Avoid entering confidential information.
// You cannot use an Oracle-provided image name as a custom image name.
// Example: `My Oracle Linux image`
DisplayName *string `mandatory:"false" json:"displayName"`
// Details for creating an image through import
ImageSourceDetails ImageSourceDetails `mandatory:"false" json:"imageSourceDetails"`
// The OCID of the instance you want to use as the basis for the image.
InstanceId *string `mandatory:"false" json:"instanceId"`
}
func (m CreateImageDetails) String() string {
return common.PointerString(m)
}
// UnmarshalJSON unmarshals from json
func (m *CreateImageDetails) UnmarshalJSON(data []byte) (e error) {
model := struct {
DisplayName *string `json:"displayName"`
ImageSourceDetails imagesourcedetails `json:"imageSourceDetails"`
InstanceId *string `json:"instanceId"`
CompartmentId *string `json:"compartmentId"`
}{}
e = json.Unmarshal(data, &model)
if e != nil {
return
}
m.DisplayName = model.DisplayName
nn, e := model.ImageSourceDetails.UnmarshalPolymorphicJSON(model.ImageSourceDetails.JsonData)
if e != nil {
return
}
m.ImageSourceDetails = nn
m.InstanceId = model.InstanceId
m.CompartmentId = model.CompartmentId
return
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateImageRequest wrapper for the CreateImage operation
type CreateImageRequest struct {
// Image creation details
CreateImageDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateImageRequest) String() string {
return common.PointerString(request)
}
// CreateImageResponse wrapper for the CreateImage operation
type CreateImageResponse struct {
// The underlying http response
RawResponse *http.Response
// The Image instance
Image `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateImageResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,28 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateInstanceConsoleConnectionDetails The details for creating a instance console connection.
// The instance console connection is created in the same compartment as the instance.
type CreateInstanceConsoleConnectionDetails struct {
// The OCID of the instance to create the console connection to.
InstanceId *string `mandatory:"true" json:"instanceId"`
// The SSH public key used to authenticate the console connection.
PublicKey *string `mandatory:"true" json:"publicKey"`
}
func (m CreateInstanceConsoleConnectionDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateInstanceConsoleConnectionRequest wrapper for the CreateInstanceConsoleConnection operation
type CreateInstanceConsoleConnectionRequest struct {
// Request object for creating an InstanceConsoleConnection
CreateInstanceConsoleConnectionDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateInstanceConsoleConnectionRequest) String() string {
return common.PointerString(request)
}
// CreateInstanceConsoleConnectionResponse wrapper for the CreateInstanceConsoleConnection operation
type CreateInstanceConsoleConnectionResponse struct {
// The underlying http response
RawResponse *http.Response
// The InstanceConsoleConnection instance
InstanceConsoleConnection `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateInstanceConsoleConnectionResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,33 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateInternetGatewayDetails The representation of CreateInternetGatewayDetails
type CreateInternetGatewayDetails struct {
// The OCID of the compartment to contain the Internet Gateway.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// Whether the gateway is enabled upon creation.
IsEnabled *bool `mandatory:"true" json:"isEnabled"`
// The OCID of the VCN the Internet Gateway is attached to.
VcnId *string `mandatory:"true" json:"vcnId"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateInternetGatewayDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
package core
import (
"github.com/oracle/oci-go-sdk/common"
"net/http"
)
// CreateInternetGatewayRequest wrapper for the CreateInternetGateway operation
type CreateInternetGatewayRequest struct {
// Details for creating a new Internet Gateway.
CreateInternetGatewayDetails `contributesTo:"body"`
// A token that uniquely identifies a request so it can be retried in case of a timeout or
// server error without risk of executing that same action again. Retry tokens expire after 24
// hours, but can be invalidated before then due to conflicting operations (for example, if a resource
// has been deleted and purged from the system, then a retry of the original creation request
// may be rejected).
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
}
func (request CreateInternetGatewayRequest) String() string {
return common.PointerString(request)
}
// CreateInternetGatewayResponse wrapper for the CreateInternetGateway operation
type CreateInternetGatewayResponse struct {
// The underlying http response
RawResponse *http.Response
// The InternetGateway instance
InternetGateway `presentIn:"body"`
// For optimistic concurrency control. See `if-match`.
Etag *string `presentIn:"header" name:"etag"`
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about
// a particular request, please provide the request ID.
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
}
func (response CreateInternetGatewayResponse) String() string {
return common.PointerString(response)
}

View File

@ -0,0 +1,38 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateIpSecConnectionDetails The representation of CreateIpSecConnectionDetails
type CreateIpSecConnectionDetails struct {
// The OCID of the compartment to contain the IPSec connection.
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The OCID of the CPE.
CpeId *string `mandatory:"true" json:"cpeId"`
// The OCID of the DRG.
DrgId *string `mandatory:"true" json:"drgId"`
// Static routes to the CPE. At least one route must be included. The CIDR must not be a
// multicast address or class E address.
// Example: `10.0.1.0/24`
StaticRoutes []string `mandatory:"true" json:"staticRoutes"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateIpSecConnectionDetails) String() string {
return common.PointerString(m)
}

View File

@ -0,0 +1,31 @@
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
// Code generated. DO NOT EDIT.
// Core Services API
//
// APIs for Networking Service, Compute Service, and Block Volume Service.
//
package core
import (
"github.com/oracle/oci-go-sdk/common"
)
// CreateLocalPeeringGatewayDetails The representation of CreateLocalPeeringGatewayDetails
type CreateLocalPeeringGatewayDetails struct {
// The OCID of the compartment containing the local peering gateway (LPG).
CompartmentId *string `mandatory:"true" json:"compartmentId"`
// The OCID of the VCN the LPG belongs to.
VcnId *string `mandatory:"true" json:"vcnId"`
// A user-friendly name. Does not have to be unique, and it's changeable. Avoid
// entering confidential information.
DisplayName *string `mandatory:"false" json:"displayName"`
}
func (m CreateLocalPeeringGatewayDetails) String() string {
return common.PointerString(m)
}

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