mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F #4298: Support for OneFlow services in GOCA
Co-authored-by: Daniel Clavijo Coca <dclavijo@opennebula.io>
This commit is contained in:
parent
5448adcd6c
commit
fdac6fa6c5
73
src/oca/go/share/examples/service_example.go
Normal file
73
src/oca/go/share/examples/service_example.go
Normal file
@ -0,0 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca"
|
||||
)
|
||||
|
||||
var rclient *goca.RESTClient
|
||||
var controller *goca.Controller
|
||||
|
||||
func init() {
|
||||
rclient = goca.NewRESTClient(
|
||||
goca.NewFlowConfig("", "", ""),
|
||||
)
|
||||
xclient := goca.NewDefaultClient(
|
||||
goca.NewConfig("", "", ""),
|
||||
)
|
||||
|
||||
controller = goca.NewController(xclient, rclient)
|
||||
}
|
||||
|
||||
func main() {
|
||||
testClient()
|
||||
testGoca()
|
||||
}
|
||||
|
||||
// Shows oneflow server up and running
|
||||
func testClient() {
|
||||
response, e := rclient.Get("service")
|
||||
|
||||
if e == nil {
|
||||
body := response.BodyMap()
|
||||
|
||||
fmt.Println(body)
|
||||
|
||||
} else {
|
||||
fmt.Println(e)
|
||||
}
|
||||
}
|
||||
|
||||
func testGoca() {
|
||||
id := 4
|
||||
|
||||
serviceCtrl := controller.Service(id)
|
||||
serv, e := serviceCtrl.Show(id)
|
||||
|
||||
if e != nil {
|
||||
log.Fatalln(e)
|
||||
}
|
||||
|
||||
fmt.Println(serv.ID)
|
||||
fmt.Println(serv.Name)
|
||||
|
||||
fmt.Println("============")
|
||||
|
||||
var status bool
|
||||
var body string
|
||||
|
||||
status, body = serviceCtrl.Shutdown(id)
|
||||
|
||||
fmt.Println(status)
|
||||
fmt.Println(body)
|
||||
|
||||
fmt.Println("============")
|
||||
|
||||
status, body = serviceCtrl.Delete(id)
|
||||
fmt.Println(status)
|
||||
fmt.Println(body)
|
||||
|
||||
fmt.Println("============")
|
||||
}
|
@ -21,9 +21,15 @@ type RPCCaller interface {
|
||||
Call(method string, args ...interface{}) (*Response, error)
|
||||
}
|
||||
|
||||
// HTTPCaller is the analogous to RPCCaller but for http endpoints
|
||||
type HTTPCaller interface {
|
||||
HTTPMethod(method string, url string, args ...interface{}) (*Response, error)
|
||||
}
|
||||
|
||||
// Controller is the controller used to make requets on various entities
|
||||
type Controller struct {
|
||||
Client RPCCaller
|
||||
Client RPCCaller
|
||||
ClientREST HTTPCaller
|
||||
}
|
||||
|
||||
// entitiesController is a controller for entitites
|
||||
|
222
src/oca/go/src/goca/flow_client.go
Normal file
222
src/oca/go/src/goca/flow_client.go
Normal file
@ -0,0 +1,222 @@
|
||||
package goca
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RESTClient for communicating with oneflow server
|
||||
type RESTClient struct {
|
||||
user string
|
||||
pass string
|
||||
address string // oneflow server address, ie: http://localhost:2474
|
||||
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// NewRESTClient Constructor
|
||||
func NewRESTClient(conf HTTPAuth) *RESTClient {
|
||||
return &RESTClient{
|
||||
user: conf.user,
|
||||
pass: conf.pass,
|
||||
address: conf.address,
|
||||
|
||||
httpClient: http.DefaultClient,
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPAuth holds credentials for a server address
|
||||
type HTTPAuth struct {
|
||||
user string
|
||||
pass string
|
||||
address string // oneflow server address, ie: http://localhost:2474
|
||||
}
|
||||
|
||||
// NewFlowConfig considering environment variables and such
|
||||
func NewFlowConfig(fuser, fpass, fURL string) HTTPAuth {
|
||||
// 1 - ONEFLOW_URL, ONEFLOW_USER and ONEFLOW_PASSWORD
|
||||
// 2 - ONE_AUTH
|
||||
// 3 - ~/.one/one_auth
|
||||
|
||||
var conf HTTPAuth
|
||||
|
||||
if fURL == "" {
|
||||
conf.address = os.Getenv("ONEFLOW_URL")
|
||||
|
||||
if conf.address == "" {
|
||||
conf.address = "http://localhost:2474"
|
||||
}
|
||||
} else {
|
||||
conf.address = fURL
|
||||
}
|
||||
|
||||
if fuser == "" && fpass == "" {
|
||||
oneAuthPath := os.Getenv("ONE_AUTH")
|
||||
if oneAuthPath == "" {
|
||||
oneAuthPath = os.Getenv("HOME") + "/.one/one_auth"
|
||||
}
|
||||
|
||||
oneAuth, err := ioutil.ReadFile(oneAuthPath)
|
||||
var auth string
|
||||
|
||||
if err == nil {
|
||||
auth = string(oneAuth)
|
||||
} else {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
credentials := strings.Split(auth, ":")
|
||||
|
||||
conf.user = credentials[0]
|
||||
conf.pass = credentials[1]
|
||||
|
||||
} else {
|
||||
conf.user = fuser
|
||||
conf.pass = fpass
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
// NewHTTPResponse Creates Response from flow http response
|
||||
func NewHTTPResponse(r *http.Response, e error) (*Response, error) {
|
||||
if e != nil {
|
||||
return &Response{}, e
|
||||
}
|
||||
|
||||
status := true
|
||||
|
||||
// HTTP 2XX
|
||||
if r.StatusCode/100 != 2 {
|
||||
status = false
|
||||
}
|
||||
|
||||
return &Response{
|
||||
status: status,
|
||||
body: bodyToStr(r),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HTTPMethod interface to client internals
|
||||
func (c *RESTClient) HTTPMethod(method string, url string, args ...interface{}) (*Response, error) {
|
||||
var e error
|
||||
var response Response
|
||||
r := &response
|
||||
|
||||
switch method {
|
||||
case "GET":
|
||||
r, e = c.Get(string(url))
|
||||
case "DELETE":
|
||||
r, e = c.Delete(string(url))
|
||||
case "POST":
|
||||
r, e = c.Post(string(url), args[1].(map[string]interface{}))
|
||||
case "PUT":
|
||||
r, e = c.Put(string(url), args[1].(map[string]interface{}))
|
||||
case "":
|
||||
return &Response{}, e
|
||||
}
|
||||
|
||||
return r, e
|
||||
}
|
||||
|
||||
// HTTP METHODS
|
||||
// The url passed to the methods is the follow up to the endpoint
|
||||
// ex. use service instead of http://localhost:2474/service
|
||||
|
||||
// Get http
|
||||
func (c *RESTClient) Get(eurl string) (*Response, error) {
|
||||
url := genurl(c.address, eurl)
|
||||
|
||||
return NewHTTPResponse(httpReq(c, "GET", url, nil))
|
||||
}
|
||||
|
||||
// Delete http
|
||||
func (c *RESTClient) Delete(eurl string) (*Response, error) {
|
||||
url := genurl(c.address, eurl)
|
||||
|
||||
return NewHTTPResponse(httpReq(c, "DELETE", url, nil))
|
||||
}
|
||||
|
||||
// Post http
|
||||
func (c *RESTClient) Post(eurl string, message map[string]interface{}) (*Response, error) {
|
||||
url := genurl(c.address, eurl)
|
||||
|
||||
return NewHTTPResponse(httpReq(c, "POST", url, message))
|
||||
|
||||
}
|
||||
|
||||
// Put http
|
||||
func (c *RESTClient) Put(eurl string, message map[string]interface{}) (*Response, error) {
|
||||
url := genurl(c.address, eurl)
|
||||
|
||||
return NewHTTPResponse(httpReq(c, "PUT", url, message))
|
||||
|
||||
}
|
||||
|
||||
// BodyMap accesses the body of the response and returns it as a map
|
||||
func (r *Response) BodyMap() map[string]interface{} {
|
||||
var bodyMap map[string]interface{}
|
||||
|
||||
if err := json.Unmarshal([]byte(r.body), &bodyMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bodyMap
|
||||
}
|
||||
|
||||
// Btomap returns http body as map
|
||||
func bodyToMap(response *http.Response) map[string]interface{} {
|
||||
var result map[string]interface{}
|
||||
|
||||
json.NewDecoder(response.Body).Decode(&result)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Btostr returns http body as string
|
||||
func bodyToStr(response *http.Response) string {
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
return string(body)
|
||||
}
|
||||
|
||||
// HELPERS
|
||||
|
||||
// General http request method for the c.
|
||||
func httpReq(c *RESTClient, method string, eurl string, message map[string]interface{}) (*http.Response, error) {
|
||||
req, err := http.NewRequest(method, eurl, bodyContent(message))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
req.SetBasicAuth(c.user, c.pass)
|
||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
return c.httpClient.Do(req)
|
||||
}
|
||||
|
||||
// concatenates flow endpoint with flow server address in a string
|
||||
func genurl(address, endpoint string) string {
|
||||
return strings.Join([]string{address, endpoint}, "/")
|
||||
}
|
||||
|
||||
// BodyContent prepares map for put/post http requests
|
||||
func bodyContent(message map[string]interface{}) *bytes.Buffer {
|
||||
represent, err := json.Marshal(message)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
return bytes.NewBuffer(represent)
|
||||
}
|
24
src/oca/go/src/goca/flow_client_test.go
Normal file
24
src/oca/go/src/goca/flow_client_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package goca
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFlowClient(t *testing.T) {
|
||||
client := createRESTClient()
|
||||
|
||||
response, e := client.HTTPMethod("GET", "service")
|
||||
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
|
||||
if response.status == false {
|
||||
t.Error(response.Body())
|
||||
}
|
||||
}
|
||||
|
||||
func createRESTClient() *RESTClient {
|
||||
config := NewFlowConfig("", "", "")
|
||||
return NewRESTClient(config)
|
||||
}
|
7
src/oca/go/src/goca/schemas/service/service.go
Normal file
7
src/oca/go/src/goca/schemas/service/service.go
Normal file
@ -0,0 +1,7 @@
|
||||
package service
|
||||
|
||||
// Service schema
|
||||
type Service struct {
|
||||
Template
|
||||
State int
|
||||
}
|
12
src/oca/go/src/goca/schemas/service/template.go
Normal file
12
src/oca/go/src/goca/schemas/service/template.go
Normal file
@ -0,0 +1,12 @@
|
||||
package service
|
||||
|
||||
// Template schema
|
||||
type Template struct {
|
||||
Name string
|
||||
Roles []map[string]interface{}
|
||||
ID int `json:",omitempty"`
|
||||
Deployment string `json:",omitempty"`
|
||||
ShutdownAction string `json:",omitempty"`
|
||||
ReadyStatusGate bool `json:",omitempty"`
|
||||
JSON map[string]interface{} `json:",omitempty"`
|
||||
}
|
233
src/oca/go/src/goca/service.go
Normal file
233
src/oca/go/src/goca/service.go
Normal file
@ -0,0 +1,233 @@
|
||||
package goca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/service"
|
||||
)
|
||||
|
||||
var endpointFService string
|
||||
|
||||
func init() {
|
||||
endpointFService = "service"
|
||||
}
|
||||
|
||||
// ServiceController interacts with oneflow service. Uses REST Client.
|
||||
type ServiceController entityController
|
||||
|
||||
// ServicesController interacts with oneflow services. Uses REST Client.
|
||||
type ServicesController entitiesController
|
||||
|
||||
// Service Controller constructor
|
||||
func (c *Controller) Service(id int) *ServiceController {
|
||||
return &ServiceController{c, id}
|
||||
}
|
||||
|
||||
// Services Controller constructor
|
||||
func (c *Controller) Services() *ServicesController {
|
||||
return &ServicesController{c}
|
||||
}
|
||||
|
||||
// NewService constructor
|
||||
func NewService(docJSON map[string]interface{}) *service.Service {
|
||||
var serv service.Service
|
||||
|
||||
template := NewTemplate(docJSON)
|
||||
|
||||
serv.Template = *template
|
||||
serv.State = template.JSON["state"].(int)
|
||||
|
||||
return &serv
|
||||
}
|
||||
|
||||
// OpenNebula Actions
|
||||
|
||||
// Show the SERVICE resource identified by <id>
|
||||
func (sc *ServiceController) Show() (*service.Service, error) {
|
||||
url := urlService(sc.ID)
|
||||
|
||||
response, e := sc.c.ClientREST.HTTPMethod("GET", url)
|
||||
|
||||
if e != nil {
|
||||
return &service.Service{}, e
|
||||
}
|
||||
|
||||
return NewService(documentJSON(response)), nil
|
||||
}
|
||||
|
||||
// Delete the SERVICE resource identified by <id>
|
||||
func (sc *ServiceController) Delete() (bool, string) {
|
||||
url := urlService(sc.ID)
|
||||
|
||||
return sc.c.boolResponse("DELETE", url, nil)
|
||||
}
|
||||
|
||||
// Shutdown running services
|
||||
func (sc *ServiceController) Shutdown() (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "shutdown",
|
||||
}
|
||||
|
||||
return sc.Action(action)
|
||||
}
|
||||
|
||||
// Recover existing service
|
||||
func (sc *ServiceController) Recover() (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "recover",
|
||||
}
|
||||
|
||||
return sc.Action(action)
|
||||
}
|
||||
|
||||
// List the contents of the SERVICE collection.
|
||||
func (ssc *ServicesController) List() (*[]*service.Service, error) {
|
||||
var services []*service.Service
|
||||
|
||||
response, e := ssc.c.ClientREST.HTTPMethod("GET", endpointFService)
|
||||
|
||||
if e != nil {
|
||||
services = append(services, &service.Service{})
|
||||
return &services, e
|
||||
}
|
||||
|
||||
documents := response.BodyMap()["DOCUMENT_POOL"].(map[string]interface{})
|
||||
|
||||
for _, v := range documents {
|
||||
service := NewService(v.(map[string]interface{}))
|
||||
services = append(services, service)
|
||||
}
|
||||
|
||||
return &services, e
|
||||
}
|
||||
|
||||
// Role operations
|
||||
|
||||
// Scale the cardinality of a service role
|
||||
func (sc *ServiceController) Scale(role string, cardinal int) (bool, string) {
|
||||
|
||||
roleBody := make(map[string]interface{})
|
||||
|
||||
roleBody["cardinality"] = 2
|
||||
roleBody["force"] = true
|
||||
|
||||
return sc.UpdateRole(role, roleBody)
|
||||
}
|
||||
|
||||
// VMAction performs the action on every VM belonging to role. Available actions:
|
||||
// shutdown, shutdown-hard, undeploy, undeploy-hard, hold, release, stop, suspend, resume, boot, delete, delete-recreate, reboot, reboot-hard, poweroff, poweroff-hard, snapshot-create.
|
||||
// Example params. Read the flow API docu.
|
||||
// map[string]interface{}{
|
||||
// "period": 60,
|
||||
// "number": 2,
|
||||
// },
|
||||
// TODO: enforce only available actions
|
||||
func (sc *ServiceController) VMAction(role, name string, params map[string]interface{}) (bool, string) {
|
||||
url := fmt.Sprintf("%s/action", urlRole(sc.ID, role))
|
||||
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": name,
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return sc.c.boolResponse("POST", url, action)
|
||||
}
|
||||
|
||||
// UpdateRole of a given Service
|
||||
func (sc *ServiceController) UpdateRole(name string, body map[string]interface{}) (bool, string) {
|
||||
url := urlRole(sc.ID, name)
|
||||
|
||||
return sc.c.boolResponse("PUT", url, body)
|
||||
}
|
||||
|
||||
// Permissions operations
|
||||
|
||||
// Chgrp service
|
||||
func (sc *ServiceController) Chgrp(gid int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"group_id": gid,
|
||||
},
|
||||
}
|
||||
|
||||
return sc.Action(action)
|
||||
}
|
||||
|
||||
// Chown service
|
||||
func (sc *ServiceController) Chown(uid, gid int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"group_id": gid,
|
||||
"user_id": uid,
|
||||
},
|
||||
}
|
||||
|
||||
return sc.Action(action)
|
||||
}
|
||||
|
||||
// Chmod service
|
||||
func (sc *ServiceController) Chmod(owner, group, other int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"owner": owner,
|
||||
"group": group,
|
||||
"other": other,
|
||||
},
|
||||
}
|
||||
|
||||
return sc.Action(action)
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
func documentJSON(response *Response) map[string]interface{} {
|
||||
responseJSON := response.BodyMap()
|
||||
|
||||
return responseJSON["DOCUMENT"].(map[string]interface{})
|
||||
}
|
||||
|
||||
func urlServiceAction(id int) string {
|
||||
return fmt.Sprintf("%s/action", urlService(id))
|
||||
}
|
||||
|
||||
func urlRole(id int, name string) string {
|
||||
return fmt.Sprintf("%s/role/%s", urlService(id), name)
|
||||
|
||||
}
|
||||
|
||||
func urlService(id int) string {
|
||||
return fmt.Sprintf("%s/%s", endpointFService, strconv.Itoa(id))
|
||||
}
|
||||
|
||||
// Action handler for existing flow services. Requires the action body.
|
||||
func (sc *ServiceController) Action(action map[string]interface{}) (bool, string) {
|
||||
url := urlServiceAction(sc.ID)
|
||||
|
||||
return sc.c.boolResponse("POST", url, action)
|
||||
}
|
||||
|
||||
func (c *Controller) boolResponse(method string, url string, body map[string]interface{}) (bool, string) {
|
||||
response, e := c.ClientREST.HTTPMethod(method, url, body)
|
||||
|
||||
if e != nil {
|
||||
return false, e.Error()
|
||||
}
|
||||
|
||||
return response.status, response.Body()
|
||||
}
|
212
src/oca/go/src/goca/service_template.go
Normal file
212
src/oca/go/src/goca/service_template.go
Normal file
@ -0,0 +1,212 @@
|
||||
package goca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/service"
|
||||
)
|
||||
|
||||
var endpointFTemplate string
|
||||
|
||||
func init() {
|
||||
endpointFTemplate = "service_template"
|
||||
}
|
||||
|
||||
// STemplateController interacts with oneflow service. Uses REST Client.
|
||||
type STemplateController entityController
|
||||
|
||||
// STemplatesController interacts with oneflow services. Uses REST Client.
|
||||
type STemplatesController entitiesController
|
||||
|
||||
// STemplate Controller constructor
|
||||
func (c *Controller) STemplate(id int) *STemplateController {
|
||||
return &STemplateController{c, id}
|
||||
}
|
||||
|
||||
// STemplates Controller constructor
|
||||
func (c *Controller) STemplates() *STemplatesController {
|
||||
return &STemplatesController{c}
|
||||
}
|
||||
|
||||
// NewTemplate constructor
|
||||
func NewTemplate(docJSON map[string]interface{}) *service.Template {
|
||||
var template service.Template
|
||||
|
||||
template.JSON = docJSON
|
||||
|
||||
body := docJSON["TEMPLATE"].(map[string]interface{})["BODY"].(map[string]interface{})
|
||||
|
||||
id, err := strconv.Atoi(docJSON["ID"].(string))
|
||||
|
||||
if err == nil {
|
||||
template.ID = id
|
||||
}
|
||||
|
||||
template.Name = body["name"].(string)
|
||||
template.Deployment = body["deployment"].(string)
|
||||
|
||||
ready, err := strconv.ParseBool(body["ready_status_gate"].(string))
|
||||
|
||||
if err == nil {
|
||||
template.ReadyStatusGate = ready
|
||||
}
|
||||
|
||||
template.Roles = body["roles"].([]map[string]interface{})
|
||||
|
||||
return &template
|
||||
}
|
||||
|
||||
// Map Template to map
|
||||
func (tc *STemplateController) Map(st *service.Template) map[string]interface{} {
|
||||
body := map[string]interface{}{
|
||||
"name": st.Name,
|
||||
"roles": st.Roles,
|
||||
"ready_status_gate": st.ReadyStatusGate,
|
||||
}
|
||||
|
||||
if st.Deployment != "" {
|
||||
body["deployment"] = st.Deployment
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
// OpenNebula Actions
|
||||
|
||||
// Create service template
|
||||
func (tc *STemplateController) Create(st *service.Template) (*service.Template, error) {
|
||||
body := tc.Map(st)
|
||||
|
||||
response, e := tc.c.ClientREST.HTTPMethod("POST", endpointFTemplate, body)
|
||||
|
||||
if e != nil {
|
||||
return &service.Template{}, e
|
||||
}
|
||||
|
||||
return NewTemplate(documentJSON(response)), nil
|
||||
}
|
||||
|
||||
// Delete the SERVICE resource identified by <id>
|
||||
func (tc *STemplateController) Delete() (bool, string) {
|
||||
url := urlTemplate(tc.ID)
|
||||
|
||||
return tc.c.boolResponse("DELETE", url, nil)
|
||||
}
|
||||
|
||||
// Update service template
|
||||
func (tc *STemplateController) Update(st *service.Template) (bool, string) {
|
||||
url := urlTemplate(tc.ID)
|
||||
body := tc.Map(st)
|
||||
|
||||
return tc.c.boolResponse("PUT", url, body)
|
||||
}
|
||||
|
||||
// Show the service template
|
||||
func (tc *STemplateController) Show() (*service.Template, error) {
|
||||
url := urlTemplate(tc.ID)
|
||||
|
||||
response, e := tc.c.ClientREST.HTTPMethod("GET", url)
|
||||
|
||||
if e != nil {
|
||||
return &service.Template{}, e
|
||||
}
|
||||
|
||||
return NewTemplate(documentJSON(response)), nil
|
||||
}
|
||||
|
||||
// List service templates
|
||||
func (tsc *STemplatesController) List() (*[]*service.Template, error) {
|
||||
var templates []*service.Template
|
||||
|
||||
response, e := tsc.c.ClientREST.HTTPMethod("GET", endpointFTemplate)
|
||||
|
||||
if e != nil {
|
||||
templates = append(templates, &service.Template{})
|
||||
return &templates, e
|
||||
}
|
||||
|
||||
documents := response.BodyMap()["DOCUMENT_POOL"].(map[string]interface{})
|
||||
|
||||
for _, v := range documents {
|
||||
template := NewTemplate(v.(map[string]interface{}))
|
||||
templates = append(templates, template)
|
||||
}
|
||||
|
||||
return &templates, e
|
||||
}
|
||||
|
||||
// Instantiate the service_template resource identified by <id>
|
||||
func (tc *STemplateController) Instantiate() (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "instantiate",
|
||||
}
|
||||
|
||||
return tc.Action(action)
|
||||
}
|
||||
|
||||
// Action handler for service_templates identified by <id>
|
||||
func (tc *STemplateController) Action(action map[string]interface{}) (bool, string) {
|
||||
url := urlTemplateAction(tc.ID)
|
||||
|
||||
return tc.c.boolResponse("POST", url, action)
|
||||
}
|
||||
|
||||
// Permissions operations
|
||||
|
||||
// Chgrp template
|
||||
func (tc *STemplateController) Chgrp(gid int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"group_id": gid,
|
||||
},
|
||||
}
|
||||
|
||||
return tc.Action(action)
|
||||
}
|
||||
|
||||
// Chown template
|
||||
func (tc *STemplateController) Chown(uid, gid int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"group_id": gid,
|
||||
"user_id": uid,
|
||||
},
|
||||
}
|
||||
|
||||
return tc.Action(action)
|
||||
}
|
||||
|
||||
// Chmod template
|
||||
func (tc *STemplateController) Chmod(owner, group, other int) (bool, string) {
|
||||
action := make(map[string]interface{})
|
||||
|
||||
action["action"] = map[string]interface{}{
|
||||
"perform": "chgrp",
|
||||
"params": map[string]interface{}{
|
||||
"owner": owner,
|
||||
"group": group,
|
||||
"other": other,
|
||||
},
|
||||
}
|
||||
|
||||
return tc.Action(action)
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
func urlTemplateAction(id int) string {
|
||||
return fmt.Sprintf("%s/action", urlTemplate(id))
|
||||
}
|
||||
|
||||
func urlTemplate(id int) string {
|
||||
return fmt.Sprintf("%s/%s", endpointFTemplate, strconv.Itoa(id))
|
||||
}
|
40
src/oca/go/src/goca/service_test.go
Normal file
40
src/oca/go/src/goca/service_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package goca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
c := createController()
|
||||
services := c.Services()
|
||||
|
||||
response, e := services.List()
|
||||
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
|
||||
fmt.Println(response)
|
||||
}
|
||||
|
||||
func createController() *Controller {
|
||||
config := NewFlowConfig("", "", "")
|
||||
client := NewRESTClient(config)
|
||||
|
||||
controller := NewController(nil)
|
||||
|
||||
controller.ClientREST = client
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func createRole(name string) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"name": name,
|
||||
"cardiniality": 1,
|
||||
"vm_template": 0,
|
||||
"elasticity_policies": []map[string]interface{}{},
|
||||
"scheduled_policies": []map[string]interface{}{},
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user