Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit 49f1bae

Browse files
author
David Chung
authored
Oracle Loadbalancer (#707)
* Initial commit * Added Cloud Compute sdk Signed-off-by: French Ben <[email protected]> * Added standard OPC Signed-off-by: French Ben <[email protected]> * Added basic BMC Config support and logging based on AWS SDK Signed-off-by: French Ben <[email protected]> * Removed unsupported API calls Signed-off-by: French Ben <[email protected]> * Added logos Signed-off-by: French Ben <[email protected]> * Better formatting Signed-off-by: French Ben <[email protected]> * Better formatting Signed-off-by: French Ben <[email protected]> * Add metadata parsing Signed-off-by: French Ben <[email protected]> * Removed old GO calls Signed-off-by: French Ben <[email protected]> * Cleaned up API calls and added support for the first call of all instances Signed-off-by: French Ben <[email protected]> * Added support for additional query parameters Signed-off-by: French Ben <[email protected]> * Updated example and added comments Signed-off-by: French Ben <[email protected]> * Only pass the querystring that are not empty Signed-off-by: French Ben <[email protected]> * Added Date and host to the request Signed-off-by: French Ben <[email protected]> * Added filter functionality for instances returned Signed-off-by: French Ben <[email protected]> * Added comments around filter Signed-off-by: French Ben <[email protected]> * Added support for Virtual NIC lookup Signed-off-by: French Ben <[email protected]> * Organized API for greater flexibility Signed-off-by: French Ben <[email protected]> * Fixed client interfact Signed-off-by: French Ben <[email protected]> * Standardize HTTP request method Signed-off-by: French Ben <[email protected]> * Updated calls for resources Signed-off-by: French Ben <[email protected]> * Added some error handling for http requests Signed-off-by: French Ben <[email protected]> * Using pointer removes the data after read Signed-off-by: French Ben <[email protected]> * Transformed requests to a standard interface allowing overwrites Signed-off-by: French Ben <[email protected]> * Added small comment around client setup Signed-off-by: French Ben <[email protected]> * Fixed bad output when no data was provided Signed-off-by: French Ben <[email protected]> * Added delete methods for Listener and BackendSet Signed-off-by: French Ben <[email protected]> * Documented the API availables Signed-off-by: French Ben <[email protected]> * Add support for loadbalancer GET Signed-off-by: French Ben <[email protected]> * Added travis integration Signed-off-by: French Ben <[email protected]> * Fixed typo in supported API Signed-off-by: French Ben <[email protected]> * Used DisplayName instead of simply Name (Matches API convention) Signed-off-by: French Ben <[email protected]> * Plural balancers Signed-off-by: French Ben <[email protected]> * Fixed sample code in main Signed-off-by: French Ben <[email protected]> * Modified travis for go matrix Signed-off-by: French Ben <[email protected]> * Added vet to the pre-script runner Signed-off-by: French Ben <[email protected]> * Removed unused dir Signed-off-by: French Ben <[email protected]> * Bump version of go due to url.URL hostname Signed-off-by: French Ben <[email protected]> * Removed go 1.7.6 from the matrix Signed-off-by: French Ben <[email protected]> * API is a lie, maps are returned for loadBalancers Signed-off-by: French Ben <[email protected]> * Added certificate struct for load balancers Signed-off-by: French Ben <[email protected]> * Listeners on LB are maps as well Signed-off-by: French Ben <[email protected]> * Added secury list and virtual network partial API support Signed-off-by: French Ben <[email protected]> * Updated README to have up to date endpoints Signed-off-by: French Ben <[email protected]> * Array of Egress and Ingress rules Signed-off-by: French Ben <[email protected]> * Ingress accept source not destination Signed-off-by: French Ben <[email protected]> * SecurityList will return content on create Signed-off-by: French Ben <[email protected]> * Export domain name for VCN Signed-off-by: French Ben <[email protected]> * Added subnet support Signed-off-by: French Ben <[email protected]> * Subnet has a security list of strings Signed-off-by: French Ben <[email protected]> * use proper types for struct Signed-off-by: French Ben <[email protected]> * Added Update of securitylist Signed-off-by: French Ben <[email protected]> * Clean update of sec list Signed-off-by: French Ben <[email protected]> * Added struct for update only on SecurityList Signed-off-by: French Ben <[email protected]> * Added debug of request method Signed-off-by: French Ben <[email protected]> * migrate sdk to infrakit Signed-off-by: David Chung <[email protected]> * remove travis for migration Signed-off-by: David Chung <[email protected]> * vendor update * fixes to make code compile, pass lint and vet Signed-off-by: David Chung <[email protected]> * fix broken build Signed-off-by: David Chung <[email protected]> * add vendor Signed-off-by: David Chung <[email protected]> * vendor Signed-off-by: David Chung <[email protected]>
1 parent db24596 commit 49f1bae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+3771
-169
lines changed

cmd/infrakit/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import (
5656
_ "github.com/docker/infrakit/pkg/run/v0/libvirt"
5757
_ "github.com/docker/infrakit/pkg/run/v0/maas"
5858
_ "github.com/docker/infrakit/pkg/run/v0/manager"
59+
_ "github.com/docker/infrakit/pkg/run/v0/oracle"
5960
_ "github.com/docker/infrakit/pkg/run/v0/packet"
6061
_ "github.com/docker/infrakit/pkg/run/v0/rackhd"
6162
_ "github.com/docker/infrakit/pkg/run/v0/selector"

pkg/provider/oracle/client/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Oracle BMC Golang SDK
2+
3+
[![GoDoc](https://godoc.org/github.com/FrenchBen/oracle-sdk-go?status.svg)](https://godoc.org/github.com/FrenchBen/oracle-sdk-go)
4+
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/FrenchBen/oracle-sdk-go/master/LICENSE)
5+
[![TravisCI](https://travis-ci.org/FrenchBen/oracle-sdk-go.svg?branch=master)](https://travis-ci.org/FrenchBen/oracle-sdk-go)
6+
[![Go Report Card](https://goreportcard.com/badge/github.com/FrenchBen/oracle-sdk-go)](https://goreportcard.com/report/github.com/FrenchBen/oracle-sdk-go)
7+
[![Badge Badge](http://doyouevenbadge.com/github.com/FrenchBen/oracle-sdk-go)](http://doyouevenbadge.com)
8+
9+
Unofficial Oracle Bare Metal Cloud Golang SDK
10+
11+
12+
13+
<p align="center">
14+
<a href="http://golang.org" target="_blank"><img alt="Go package" src="https://golang.org/doc/gopher/pencil/gopherhat.jpg" width="20%" /></a>
15+
</p>
16+
<p align="center">
17+
<img src="https://cdn4.iconfinder.com/data/icons/linecon/512/add-128.png" alt="plus" />
18+
</p>
19+
<p align="center">
20+
<a href="https://www.oraclecloud.com/" target="_blank"><img src="https://static1.squarespace.com/static/587d94cf4402432706cdd02d/t/58cee1bd1b10e37dbd70b243/1489953226294/oracle-logo" alt="Oracle Cloud Logo"/></a>
21+
</p>
22+
23+
24+
25+
26+
## Requirements
27+
The following variables are needed in order to make successful calls to the BMC API
28+
29+
* User - The user for the compartment
30+
```
31+
user=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq
32+
```
33+
* Fingerprint - The API key fingerprint; this fingerprint can be found within the Oracle BMC console
34+
```
35+
fingerprint=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34
36+
```
37+
* KeyFile - The API key file location
38+
```
39+
key_file=~/.oraclebmc/bmcs_api_key.pem
40+
```
41+
* Tenancy - Your tenancy compartment ID
42+
```
43+
tenancy=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq
44+
```
45+
* Region - The region corresponding to the compartment in use
46+
```
47+
region=us-ashburn-1
48+
```
49+
50+
A default config file can also be used; the typical location for the Oracle BMC config is: `~/.oraclebmc/config`
51+
The config file should have the following format:
52+
```
53+
[DEFAULT]
54+
user=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq
55+
fingerprint=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34
56+
key_file=~/.oraclebmc/bmcs_api_key.pem
57+
tenancy=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq
58+
region=us-ashburn-1
59+
```
60+
61+
# Support Endpoint
62+
63+
The following endpoints are provided by the [Oracle BMC API](https://docs.us-phoenix-1.oraclecloud.com/api/)
64+
65+
| Name | Support |
66+
| --- | --- |
67+
| Audit API | NO |
68+
| Database Service API | NO |
69+
| Core Services API | YES-partial |
70+
| Identity and Access Management Service API | NO |
71+
| Load Balancing Service API | YES-partial |
72+
| Object Storage Service API | NO |
73+
| S3 Object Storage Service API | NO |
74+
75+
Only API supported at the moment is to get instance details
76+
* List instances
77+
* Get instance
78+
* List VNIC
79+
* Get VNIC
80+
* List VNICAttachment
81+
* Get VNICAttachment
82+
* List SecurityList
83+
* Get SecurityList
84+
* Create SecurityList
85+
* Update SecurityList
86+
* Delete SecurityList
87+
* List VirtualCloudNetwork
88+
* Get VirtualCloudNetwork
89+
* List Backend
90+
* Get Backend
91+
* Create Backend
92+
* Delete Backend
93+
* List BackendSet
94+
* Get BackendSet
95+
* Create BackendSet
96+
* Delete BackendSet
97+
* Create Listener
98+
* Delete Listener
99+
* List LoadBalancer
100+
* Get LoadBalancer
101+
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package api
2+
3+
import (
4+
"crypto/rsa"
5+
"encoding/json"
6+
"fmt"
7+
"io/ioutil"
8+
"log"
9+
"net/http"
10+
"path/filepath"
11+
"time"
12+
13+
"github.com/Sirupsen/logrus"
14+
"github.com/docker/infrakit/pkg/provider/oracle/client/bmc"
15+
"golang.org/x/crypto/ssh"
16+
)
17+
18+
const (
19+
// EndpointFormat provides the base template for all API url
20+
EndpointFormat = "https://iaas.%s.oraclecloud.com/%s/"
21+
// CoreAPIVersion is the API version for core services
22+
CoreAPIVersion = "20160918"
23+
// LoadBalancerAPIVersion is the API version for load balancing services
24+
LoadBalancerAPIVersion = "20170115"
25+
metaDataURL = "http://169.254.169.254/opc/v1/instance/"
26+
)
27+
28+
// Config holds the general API bmcConf
29+
type config struct {
30+
}
31+
32+
// Client represents the struct for basic api calls
33+
type Client struct {
34+
apiKey string
35+
apiPrivateKey *rsa.PrivateKey
36+
APIRegion string
37+
httpClient *http.Client
38+
}
39+
40+
type metaData struct {
41+
AvailabilityDomain string `json:"availabilityDomain"`
42+
CompartmentID string `json:"compartmentId"`
43+
DisplayName string `json:"displayName"`
44+
ID string `json:"id"`
45+
Image string `json:"image"`
46+
Metadata struct {
47+
PublicKey string `json:"ssh_authorized_keys"`
48+
UserData string `json:"user_data"`
49+
} `json:"metadata"`
50+
Region string `json:"region"`
51+
Shape string `json:"shape"`
52+
State string `json:"state"`
53+
TimeCreated string `json:"timeCreated"`
54+
}
55+
56+
// NewClient creates a new, unauthenticated compute Client.
57+
func NewClient(bmcConf *bmc.Config) (*Client, error) {
58+
apiKey := fmt.Sprintf("%s/%s/%s", *bmcConf.Tenancy, *bmcConf.User, *bmcConf.Fingerprint)
59+
logrus.Debug("Api Key: ", apiKey)
60+
privateKey, err := loadKeyFromFile(bmcConf.KeyFile, bmcConf.PassPhrase)
61+
if err != nil {
62+
// If we failed to read the file because the key does not exist,
63+
// just issue a warning and continue.
64+
logrus.Error("private key error: ", err)
65+
return nil, err
66+
}
67+
68+
return &Client{
69+
apiKey: apiKey,
70+
apiPrivateKey: privateKey,
71+
APIRegion: getRegion(bmcConf),
72+
httpClient: &http.Client{
73+
Transport: &http.Transport{
74+
Proxy: http.ProxyFromEnvironment,
75+
TLSHandshakeTimeout: 120 * time.Second},
76+
},
77+
}, nil
78+
}
79+
80+
// only load keys that have no password for now :(
81+
func loadKeyFromFile(pemFile *string, passphrase *string) (*rsa.PrivateKey, error) {
82+
pemPath, err := filepath.Abs(*pemFile)
83+
logrus.Debugf("Loading key file from: %s - %s", *pemFile, pemPath)
84+
if err != nil {
85+
logrus.Errorf("KeyFile error: %s", err)
86+
return nil, err
87+
}
88+
pemBytes, err := ioutil.ReadFile(pemPath)
89+
if err != nil {
90+
return nil, err
91+
}
92+
// check if a passphrase was given
93+
var rawKey interface{}
94+
if passphrase != nil {
95+
rawKey, err = ssh.ParseRawPrivateKeyWithPassphrase(pemBytes, []byte(*passphrase))
96+
} else {
97+
rawKey, err = ssh.ParseRawPrivateKey(pemBytes)
98+
}
99+
if err != nil {
100+
logrus.Errorf("Cannot parse private key: %s", err)
101+
}
102+
rsaKey, ok := rawKey.(*rsa.PrivateKey)
103+
if !ok {
104+
logrus.Fatalf("Could not create private key: %v", rawKey)
105+
return nil, err
106+
}
107+
return rsaKey, err
108+
}
109+
110+
func getRegion(bmcConf *bmc.Config) string {
111+
if bmcConf.Region != nil {
112+
return *bmcConf.Region
113+
}
114+
res, err := http.Get(metaDataURL)
115+
if err != nil {
116+
log.Fatalf("Error getting metadata: %s", err)
117+
}
118+
defer res.Body.Close()
119+
body, err := ioutil.ReadAll(res.Body)
120+
if err != nil {
121+
log.Fatal(err)
122+
}
123+
var meta = new(metaData)
124+
err = json.Unmarshal(body, &meta)
125+
if err != nil {
126+
log.Fatalf("Error parsing JSON: %s", err)
127+
}
128+
return meta.Region
129+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package api
2+
3+
import (
4+
"bytes"
5+
"crypto/sha256"
6+
"encoding/base64"
7+
"encoding/json"
8+
"io"
9+
"net/http"
10+
"net/url"
11+
"strconv"
12+
"strings"
13+
"time"
14+
15+
"github.com/Sirupsen/logrus"
16+
"github.com/spacemonkeygo/httpsig"
17+
)
18+
19+
// Signing details: https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/signingrequests.htm
20+
21+
var headersConst = []string{"date", "(request-target)", "host"}
22+
23+
// Clienter is the client interface for all requests
24+
type Clienter interface {
25+
Request(string, string, interface{}) (*http.Response, error)
26+
}
27+
28+
func (c *Client) signAuthHeader(req *http.Request, body []byte) {
29+
// Add missing defaults
30+
if req.Header.Get("Content-Type") == "" {
31+
req.Header.Set("Content-Type", "application/json")
32+
}
33+
if req.Header.Get("Host") == "" {
34+
req.Header.Set("Host", req.URL.Hostname())
35+
}
36+
if req.Header.Get("Date") == "" {
37+
t := time.Now()
38+
req.Header.Set("Date", t.Format(time.RFC1123))
39+
}
40+
headersToSign := headersConst
41+
if strings.HasPrefix(req.Method, "P") {
42+
43+
headersToSign = append(headersConst, "x-content-sha256", "content-type", "content-length")
44+
bodyHash := sha256.Sum256(body)
45+
req.Header.Set("Content-Length", strconv.Itoa(len(body)))
46+
req.Header.Set("X-Content-Sha256", base64.StdEncoding.EncodeToString(bodyHash[:]))
47+
}
48+
49+
signer := httpsig.NewRSASHA256Signer(c.apiKey, c.apiPrivateKey, headersToSign)
50+
err := signer.Sign(req)
51+
if err != nil {
52+
logrus.Fatalf("Could not sign request: %s", err)
53+
}
54+
55+
return
56+
}
57+
58+
// Request request a resource from Oracle
59+
func (c *Client) Request(method string, reqURL string, body interface{}) (*http.Response, error) {
60+
// Parse URL Path
61+
urlPath, err := url.Parse(reqURL)
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
// Marshall request body
67+
var requestBody io.ReadSeeker
68+
var marshaled []byte
69+
if body != nil {
70+
marshaled, err = json.Marshal(body)
71+
logrus.Debug("Body: ", string(marshaled))
72+
if err != nil {
73+
return nil, err
74+
}
75+
requestBody = bytes.NewReader(marshaled)
76+
}
77+
78+
// Create Request
79+
req, err := http.NewRequest(method, urlPath.String(), requestBody)
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
c.signAuthHeader(req, marshaled)
85+
logrus.Debug("Auth: ", req.Header)
86+
logrus.Debug("Request URL: ", req.URL.String(), " Method: ", method)
87+
return c.httpClient.Do(req)
88+
}

0 commit comments

Comments
 (0)