Skip to content

Commit

Permalink
Merge pull request #133 from aswinmprabhu/master
Browse files Browse the repository at this point in the history
Add rackspace authentication package
  • Loading branch information
PratikDhanave authored Mar 27, 2019
2 parents bd9cb98 + a07c627 commit ce252de
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 1 deletion.
3 changes: 2 additions & 1 deletion compute/droplet/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"encoding/json"
"errors"
"fmt"
digioceanAuth "github.com/cloudlibz/gocloud/digioceanauth"
"io/ioutil"
"net/http"
"strconv"

digioceanAuth "github.com/cloudlibz/gocloud/digioceanauth"
)

// dropletBasePath is the endpoint URL for digitalocean API.
Expand Down
76 changes: 76 additions & 0 deletions compute/rackspacecompute/instance.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,83 @@
package rackspacecompute

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"github.com/cloudlibz/gocloud/rackspaceauth"
)

var cloudserverEndpoints = rackspaceauth.Token.Endpoints["cloudServer"]

// CreateNode function creates a new rackspacecompute instance.
func (rackspacecompute *Rackspacecompute) CreateNode(request interface{}) (resp interface{}, err error) {
var cloudserverInstance Cloudserver // Initialize Cloudserver struct
var region string
rackSpaceAuthToken := rackspaceauth.Token.RackSpaceAuthToken // Fetch the DigiOceanAccessToken

param := request.(map[string]interface{})

for key, value := range param {

switch key {

case "Name":
name, _ := value.(string)
cloudserverInstance.Name = name

case "ImageRef":
imageparam, _ := value.(string)
cloudserverInstance.ImageRef = imageparam

case "FlavourRef":
flavourparam, _ := value.(string)
cloudserverInstance.FlavorRef = flavourparam

case "Region":
region, _ = value.(string)
} // Closes switch-case

} // Closes for loop

rackspacecompute.Server = cloudserverInstance
rackspacecomputeJSON, _ := json.Marshal(rackspacecompute)

var cloudserverEndpoint string
flag := 0
for _, endpoint := range cloudserverEndpoints {
if endpoint.Region == region {
cloudserverEndpoint = endpoint.URL
flag = 1
break
}
}
if flag == 0 {
return nil, fmt.Errorf("Could not find a endpoint for the giver region : %s", region)
}

createNodereq, err := http.NewRequest("POST", cloudserverEndpoint, bytes.NewBuffer(rackspacecomputeJSON))
if err != nil {
fmt.Println(err)
}
createNodereq.Header.Set("Content-Type", "application/json")
createNodereq.Header.Set("X-Auth-Token", rackSpaceAuthToken)

createNoderesp, err := http.DefaultClient.Do(createNodereq)
if err != nil {
fmt.Println(err)
}

defer createNoderesp.Body.Close()

responseBody, err := ioutil.ReadAll(createNoderesp.Body)
createNoderesponse := make(map[string]interface{})
createNoderesponse["status"] = createNoderesp.StatusCode
createNoderesponse["body"] = string(responseBody)
resp = createNoderesponse

return resp, err
}

Expand Down
20 changes: 20 additions & 0 deletions compute/rackspacecompute/instance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package rackspacecompute

import "testing"

func TestCreateNode(t *testing.T) {

var rackspacecompute Rackspacecompute

request := map[string]interface{}{
"Name": "testcloudserver",
"ImageRef": "3afe97b2-26dc-49c5-a2cc-a2fc8d80c001",
"FlavourRef": "2",
"Region": "DFW",
}
_, err := rackspacecompute.CreateNode(request)

if err != nil {
t.Errorf("Test Fail")
}
}
8 changes: 8 additions & 0 deletions compute/rackspacecompute/rackspacecompute.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@ package rackspacecompute

// Rackspacecompute represents a request to create a Rackspace compute instance.
type Rackspacecompute struct {
Server Cloudserver `json:"server"`
}

// Cloudserver represents a node of cloud server on rackspace
type Cloudserver struct {
Name string `json:"name"`
ImageRef string `json:"imageRef"`
FlavorRef string `json:"flavorRef"`
}
3 changes: 3 additions & 0 deletions gocloud/gocloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gocloud

import (
"fmt"

"github.com/cloudlibz/gocloud/ali"
aliAuth "github.com/cloudlibz/gocloud/aliauth"
awsAuth "github.com/cloudlibz/gocloud/auth"
Expand All @@ -12,6 +13,7 @@ import (
"github.com/cloudlibz/gocloud/google"
"github.com/cloudlibz/gocloud/openstack"
"github.com/cloudlibz/gocloud/rackspace"
"github.com/cloudlibz/gocloud/rackspaceauth"
"github.com/cloudlibz/gocloud/vultr"
"github.com/cloudlibz/gocloud/vultrauth"
)
Expand Down Expand Up @@ -112,6 +114,7 @@ func CloudProvider(provider string) (Gocloud, error) {
return new(ali.Ali), nil

case Rackspaceprovider:
rackspaceauth.LoadConfigAndAuthenticate()
return new(rackspace.Rackspace), nil

case Vultrprovider:
Expand Down
106 changes: 106 additions & 0 deletions rackspaceauth/rackspaceauth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package rackspaceauth

import (
"bytes"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"os"
)

// TokenSource struct for representing RackSpace credentials.
type TokenSource struct {
RackSpaceTenantID string
RackSpaceTenantName string
RackSpaceAuthToken string
RackSpaceAPIKey string
RackSpaceUsername string
Endpoints map[string][]Endpoint
}

// Endpoint represents the enpoint of a particular service
type Endpoint struct {
URL string `json:"publicURL"`
Region string `json:"region"`
}

// Token is a variable of type TokenSource.
var Token TokenSource

// LoadConfigAndAuthenticate loads the RackSpace credentials.
func LoadConfigAndAuthenticate() {

// Read from file first.
var home = os.Getenv("HOME")
file, _ := os.Open(home + "/.gocloud" + "/rackspacecloudconfig.json")

// Defer the closing of our file so that we can parse it later on.
defer file.Close()

// We initialize TokenSource struct.
decoder := json.NewDecoder(file)
Token = TokenSource{}
_ = decoder.Decode(&Token)

if Token.RackSpaceAPIKey == "" || Token.RackSpaceUsername == "" {
// If digioceancloudconfig.json doesn't exist, look for credentials as environment variables.

Token.RackSpaceAPIKey = os.Getenv("RackSpaceAPIKey")
Token.RackSpaceUsername = os.Getenv("RackSpaceUsername")
if Token.RackSpaceAPIKey == "" || Token.RackSpaceUsername == "" {
log.Fatalln("Cannot get access token for RackSpace.")
}
}

// prepare the authoriation request
url := "https://identity.api.rackspacecloud.com/v2.0/tokens"
authRequestData := map[string]interface{}{
"auth": map[string]interface{}{
"RAX-KSKEY:apiKeyCredentials": map[string]interface{}{
"username": Token.RackSpaceUsername,
"apiKey": Token.RackSpaceAPIKey,
},
},
}
jsonStr, err := json.Marshal(authRequestData)
if err != nil {
log.Fatalln("Failed to marshal json")
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
if err != nil {
log.Fatalln("Failed to create the request")
}
req.Header.Set("Content-Type", "application/json")

// make the authorization request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalln("Failed to make the request")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln("Failed to read the response body")
}

// Extract the Auth Token and the tenant details
respJSON := make(map[string]interface{})
err = json.Unmarshal(body, &respJSON)
if err != nil {
log.Fatalln("Failed to unmarshal response JSON")
}
accessJSON := respJSON["access"].(map[string]interface{})
tokenJSON := accessJSON["token"].(map[string]interface{})
serviceCatalogJSON := accessJSON["serviceCatalog"].([]map[string]interface{})
for _, service := range serviceCatalogJSON {
endpointsBytes, _ := json.Marshal(service["endpoints"].([]map[string]interface{}))
serviceName := service["name"].(string)
json.Unmarshal(endpointsBytes, Token.Endpoints[serviceName])
}
Token.RackSpaceAuthToken = tokenJSON["id"].(string)
tenantJSON := tokenJSON["tenant"].(map[string]interface{})
Token.RackSpaceTenantID = tenantJSON["id"].(string)
Token.RackSpaceTenantName = tenantJSON["name"].(string)
}

0 comments on commit ce252de

Please sign in to comment.