From 47744ccc2dbc0ab49ca703ed502e65602cd8c710 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 17 Nov 2021 19:22:40 +0100 Subject: [PATCH 1/3] Remove the XO SDK from this repository. Signed-off-by: Ringo De Smet --- client/acl.go | 110 ------ client/acl_test.go | 84 ----- client/client.go | 306 ---------------- client/client_test.go | 107 ------ client/cloud_config.go | 154 -------- client/errors.go | 13 - client/errors_test.go | 22 -- client/go.mod | 8 - client/go.sum | 5 - client/host.go | 123 ------- client/host_test.go | 114 ------ client/network.go | 138 -------- client/network_test.go | 94 ----- client/pif.go | 60 ---- client/pif_test.go | 31 -- client/pool.go | 81 ----- client/pool_test.go | 66 ---- client/resource_set.go | 253 ------------- client/resource_set_test.go | 72 ---- client/setup_test.go | 62 ---- client/state.go | 343 ------------------ client/storage_repository.go | 117 ------ client/storage_repository_test.go | 83 ----- client/tag.go | 95 ----- client/template.go | 104 ------ client/template_test.go | 62 ---- client/user.go | 135 ------- client/user_test.go | 39 -- client/vdi.go | 240 ------------- client/vdi_test.go | 108 ------ client/vif.go | 148 -------- client/vif_test.go | 93 ----- client/vm.go | 569 ------------------------------ client/vm_test.go | 231 ------------ 34 files changed, 4270 deletions(-) delete mode 100644 client/acl.go delete mode 100644 client/acl_test.go delete mode 100644 client/client.go delete mode 100644 client/client_test.go delete mode 100644 client/cloud_config.go delete mode 100644 client/errors.go delete mode 100644 client/errors_test.go delete mode 100644 client/go.mod delete mode 100644 client/go.sum delete mode 100644 client/host.go delete mode 100644 client/host_test.go delete mode 100644 client/network.go delete mode 100644 client/network_test.go delete mode 100644 client/pif.go delete mode 100644 client/pif_test.go delete mode 100644 client/pool.go delete mode 100644 client/pool_test.go delete mode 100644 client/resource_set.go delete mode 100644 client/resource_set_test.go delete mode 100644 client/setup_test.go delete mode 100644 client/state.go delete mode 100644 client/storage_repository.go delete mode 100644 client/storage_repository_test.go delete mode 100644 client/tag.go delete mode 100644 client/template.go delete mode 100644 client/template_test.go delete mode 100644 client/user.go delete mode 100644 client/user_test.go delete mode 100644 client/vdi.go delete mode 100644 client/vdi_test.go delete mode 100644 client/vif.go delete mode 100644 client/vif_test.go delete mode 100644 client/vm.go delete mode 100644 client/vm_test.go diff --git a/client/acl.go b/client/acl.go deleted file mode 100644 index 1be84caa..00000000 --- a/client/acl.go +++ /dev/null @@ -1,110 +0,0 @@ -package client - -import ( - "errors" - "log" -) - -type Acl struct { - Id string - Action string - Subject string - Object string -} - -func (acl Acl) Compare(obj interface{}) bool { - other := obj.(Acl) - - if acl.Id == other.Id { - return true - } - - if acl.Action == other.Action && acl.Subject == other.Subject && acl.Object == other.Object { - return true - } - - return false -} - -func (c *Client) CreateAcl(acl Acl) (*Acl, error) { - var success bool - params := map[string]interface{}{ - "subject": acl.Subject, - "object": acl.Object, - "action": acl.Action, - } - err := c.Call("acl.add", params, &success) - - if err != nil { - return nil, err - } - - return c.GetAcl(acl) -} - -func (c *Client) GetAcls() ([]Acl, error) { - params := map[string]interface{}{ - "dummy": "dummy", - } - acls := []Acl{} - err := c.Call("acl.get", params, &acls) - - if err != nil { - return nil, err - } - log.Printf("[DEBUG] Found the following ACLs: %v\n", acls) - return acls, nil -} - -func (c *Client) GetAcl(aclReq Acl) (*Acl, error) { - acls, err := c.GetAcls() - if err != nil { - return nil, err - } - - var foundAcl Acl - for _, acl := range acls { - if acl.Compare(aclReq) { - foundAcl = acl - } - } - - if foundAcl.Id == "" { - return nil, NotFound{Query: aclReq} - } - - return &foundAcl, nil -} - -func (c *Client) DeleteAcl(acl Acl) error { - var err error - var aclRef *Acl - if getAclById(acl) { - aclRef, err = c.GetAcl(acl) - acl = *aclRef - } - var success bool - params := map[string]interface{}{ - "subject": acl.Subject, - "object": acl.Object, - "action": acl.Action, - } - err = c.Call("acl.remove", params, &success) - - if err != nil { - return err - } - - if !success { - return errors.New("failed to delete acl") - } - return nil -} - -func getAclById(acl Acl) bool { - if acl.Id != "" && acl.Subject == "" && acl.Object == "" && acl.Action == "" { - return true - } - - return false -} diff --git a/client/acl_test.go b/client/acl_test.go deleted file mode 100644 index a8998b78..00000000 --- a/client/acl_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package client - -import ( - "fmt" - "testing" -) - -func TestCreateAclAndDeleteAcl(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - expectedAcl := Acl{ - Subject: fmt.Sprintf("%s-%s", integrationTestPrefix, "acl"), - Action: "viewer", - Object: accVm.Id, - } - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - acl, err := c.CreateAcl(expectedAcl) - - if err != nil { - t.Fatalf("failed to create acl with error: %v", err) - } - - if acl == nil { - t.Fatalf("expected to receive non-nil Acl") - } - - if acl.Id == "" { - t.Errorf("expected Acl to have a non-empty Id") - } - - if acl.Subject != expectedAcl.Subject { - t.Errorf("expected acl's subject `%s` to match `%s`", acl.Subject, expectedAcl.Subject) - } - - err = c.DeleteAcl(expectedAcl) - - if err != nil { - t.Errorf("failed to delete acl with error: %v", err) - } -} - -func TestGetAcl(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - expectedAcl := Acl{ - Subject: fmt.Sprintf("%s-%s", integrationTestPrefix, "acl"), - Action: "viewer", - Object: accVm.Id, - } - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - acl, err := c.CreateAcl(expectedAcl) - - if err != nil { - t.Fatalf("failed to create acl with error: %v", err) - } - - if acl == nil { - t.Fatalf("expected to receive non-nil Acl") - } - - if acl.Id == "" { - t.Errorf("expected Acl to have a non-empty Id") - } - - _, err = c.GetAcl(Acl{Id: acl.Id}) - - if err != nil { - t.Errorf("failed to find Acl by id `%s` with error: %v", acl.Id, err) - } - - err = c.DeleteAcl(*acl) - - if err != nil { - t.Errorf("failed to delete acl with error: %v", err) - } -} diff --git a/client/client.go b/client/client.go deleted file mode 100644 index e753d12a..00000000 --- a/client/client.go +++ /dev/null @@ -1,306 +0,0 @@ -package client - -import ( - "context" - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "log" - "net/http" - "os" - "reflect" - "time" - - gorillawebsocket "github.com/gorilla/websocket" - "github.com/sourcegraph/jsonrpc2" - "github.com/sourcegraph/jsonrpc2/websocket" -) - -const ( - // Maximum message size allowed from peer. - MaxMessageSize = 4096 - PongWait = 60 * time.Second -) - -type XOClient interface { - GetObjectsWithTags(tags []string) ([]Object, error) - - CreateVm(vmReq Vm, d time.Duration) (*Vm, error) - GetVm(vmReq Vm) (*Vm, error) - GetVms(vm Vm) ([]Vm, error) - UpdateVm(vmReq Vm) (*Vm, error) - DeleteVm(id string) error - HaltVm(vmReq Vm) error - StartVm(id string) error - - GetCloudConfigByName(name string) ([]CloudConfig, error) - CreateCloudConfig(name, template string) (*CloudConfig, error) - GetCloudConfig(id string) (*CloudConfig, error) - DeleteCloudConfig(id string) error - GetAllCloudConfigs() ([]CloudConfig, error) - - GetHostById(id string) (host Host, err error) - GetHostByName(nameLabel string) (hosts []Host, err error) - - GetPools(pool Pool) ([]Pool, error) - GetPoolByName(name string) (pools []Pool, err error) - - GetSortedHosts(host Host, sortBy, sortOrder string) (hosts []Host, err error) - - CreateResourceSet(rsReq ResourceSet) (*ResourceSet, error) - GetResourceSets() ([]ResourceSet, error) - GetResourceSet(rsReq ResourceSet) ([]ResourceSet, error) - GetResourceSetById(id string) (*ResourceSet, error) - DeleteResourceSet(rsReq ResourceSet) error - AddResourceSetSubject(rsReq ResourceSet, subject string) error - AddResourceSetObject(rsReq ResourceSet, object string) error - AddResourceSetLimit(rsReq ResourceSet, limit string, quantity int) error - RemoveResourceSetSubject(rsReq ResourceSet, subject string) error - RemoveResourceSetObject(rsReq ResourceSet, object string) error - RemoveResourceSetLimit(rsReq ResourceSet, limit string) error - - CreateUser(user User) (*User, error) - GetAllUsers() ([]User, error) - GetUser(userReq User) (*User, error) - DeleteUser(userReq User) error - - CreateNetwork(netReq Network) (*Network, error) - GetNetwork(netReq Network) (*Network, error) - GetNetworks() ([]Network, error) - DeleteNetwork(id string) error - - GetPIF(pifReq PIF) (pifs []PIF, err error) - GetPIFByDevice(dev string, vlan int) ([]PIF, error) - - GetStorageRepository(sr StorageRepository) ([]StorageRepository, error) - GetStorageRepositoryById(id string) (StorageRepository, error) - - GetTemplate(template Template) ([]Template, error) - - GetVDIs(vdiReq VDI) ([]VDI, error) - UpdateVDI(d Disk) error - - CreateAcl(acl Acl) (*Acl, error) - GetAcl(aclReq Acl) (*Acl, error) - DeleteAcl(acl Acl) error - - AddTag(id, tag string) error - RemoveTag(id, tag string) error - - GetDisks(vm *Vm) ([]Disk, error) - CreateDisk(vm Vm, d Disk) (string, error) - DeleteDisk(vm Vm, d Disk) error - ConnectDisk(d Disk) error - DisconnectDisk(d Disk) error - - GetVIF(vifReq *VIF) (*VIF, error) - GetVIFs(vm *Vm) ([]VIF, error) - CreateVIF(vm *Vm, vif *VIF) (*VIF, error) - DeleteVIF(vifReq *VIF) (err error) - DisconnectVIF(vifReq *VIF) (err error) - ConnectVIF(vifReq *VIF) (err error) - - GetCdroms(vm *Vm) ([]Disk, error) - EjectCd(id string) error - InsertCd(vmId, cdId string) error -} - -type Client struct { - rpc jsonrpc2.JSONRPC2 -} - -type Config struct { - Url string - Username string - Password string - InsecureSkipVerify bool -} - -var dialer = gorillawebsocket.Dialer{ - ReadBufferSize: MaxMessageSize, - WriteBufferSize: MaxMessageSize, -} - -func GetConfigFromEnv() Config { - var url string - var username string - var password string - insecure := false - if v := os.Getenv("XOA_URL"); v != "" { - url = v - } - if v := os.Getenv("XOA_USER"); v != "" { - username = v - } - if v := os.Getenv("XOA_PASSWORD"); v != "" { - password = v - } - if v := os.Getenv("XOA_INSECURE"); v != "" { - insecure = true - } - return Config{ - Url: url, - Username: username, - Password: password, - InsecureSkipVerify: insecure, - } -} - -func NewClient(config Config) (XOClient, error) { - url := config.Url - username := config.Username - password := config.Password - skipVerify := config.InsecureSkipVerify - - if skipVerify { - dialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - - ws, _, err := dialer.Dial(fmt.Sprintf("%s/api/", url), http.Header{}) - - if err != nil { - return nil, err - } - - objStream := websocket.NewObjectStream(ws) - var h jsonrpc2.Handler - h = &handler{} - c := jsonrpc2.NewConn(context.Background(), objStream, h) - - reqParams := map[string]interface{}{ - "email": username, - "password": password, - } - var reply signInResponse - err = c.Call(context.Background(), "session.signInWithPassword", reqParams, &reply) - if err != nil { - return nil, err - } - return &Client{ - rpc: c, - }, nil -} - -func (c *Client) Call(method string, params, result interface{}, opt ...jsonrpc2.CallOption) error { - err := c.rpc.Call(context.Background(), method, params, result, opt...) - var callRes interface{} - t := reflect.TypeOf(result) - if t == nil || t.Kind() != reflect.Ptr { - callRes = result - } else { - callRes = reflect.ValueOf(result).Elem() - } - log.Printf("[TRACE] Made rpc call `%s` with params: %v and received %+v: result with error: %v\n", method, params, callRes, err) - - if err != nil { - rpcErr, ok := err.(*jsonrpc2.Error) - - if !ok { - return err - } - - data := rpcErr.Data - - if data == nil { - return err - } - - return errors.New(fmt.Sprintf("%s: %s", err, *data)) - } - return nil -} - -type XoObject interface { - Compare(obj interface{}) bool -} - -func (c *Client) getObjectTypeFilter(obj XoObject) map[string]interface{} { - xoApiType := "" - switch t := obj.(type) { - case Network: - xoApiType = "network" - case PIF: - xoApiType = "PIF" - case Pool: - xoApiType = "pool" - case Host: - xoApiType = "host" - case StorageRepository: - xoApiType = "SR" - case Vm: - xoApiType = "VM" - case Template: - xoApiType = "VM-template" - case VIF: - xoApiType = "VIF" - case VBD: - xoApiType = "VBD" - case VDI: - xoApiType = "VDI" - default: - panic(fmt.Sprintf("XO client does not support type: %T", t)) - } - return map[string]interface{}{ - "filter": map[string]string{ - "type": xoApiType, - }, - } -} - -func (c *Client) GetAllObjectsOfType(obj XoObject, response interface{}) error { - return c.Call("xo.getAllObjects", c.getObjectTypeFilter(obj), response) -} - -func (c *Client) FindFromGetAllObjects(obj XoObject) (interface{}, error) { - var objsRes struct { - Objects map[string]interface{} `json:"-"` - } - err := c.GetAllObjectsOfType(obj, &objsRes.Objects) - if err != nil { - return obj, err - } - - found := false - t := reflect.TypeOf(obj) - objs := reflect.MakeSlice(reflect.SliceOf(t), 0, 0) - for _, resObj := range objsRes.Objects { - v, ok := resObj.(map[string]interface{}) - if !ok { - return obj, errors.New("Could not coerce interface{} into map") - } - b, err := json.Marshal(v) - - if err != nil { - return objs, err - } - value := reflect.New(t) - err = json.Unmarshal(b, value.Interface()) - if err != nil { - return objs, err - } - if obj.Compare(value.Elem().Interface()) { - found = true - objs = reflect.Append(objs, value.Elem()) - } - } - if !found { - return objs, NotFound{Query: obj} - } - - log.Printf("[DEBUG] Found the following objects for type '%v' from xo.getAllObjects: %+v\n", t, objs) - - return objs.Interface(), nil -} - -type handler struct{} - -func (h *handler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) { - // We do not react to json rpc notifications and are only acting as a client. - // So there is no need to handle these callbacks. -} - -type signInResponse struct { - Email string `json:"email,omitempty"` - Id string `json:"id,omitempty"` -} diff --git a/client/client_test.go b/client/client_test.go deleted file mode 100644 index 728a69d3..00000000 --- a/client/client_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package client - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "testing" - - "github.com/sourcegraph/jsonrpc2" -) - -type jsonRPCFail struct { - err error -} - -func (rpc jsonRPCFail) Call(ctx context.Context, method string, params, result interface{}, opt ...jsonrpc2.CallOption) error { - return rpc.err -} - -func (rpc jsonRPCFail) Notify(ctx context.Context, method string, params interface{}, opt ...jsonrpc2.CallOption) error { - return nil -} - -func (rpc jsonRPCFail) Close() error { - return nil -} - -func TestCall_withJsonRPC2Error(t *testing.T) { - var jsonRpcErr string = `{"errors":[{"code":null,"reason":"type","message":"must be string, but is object","property":"@.template"}]}` - rpcCode := 10 - msg := "invalid parameters" - var expectedErrMsg string = fmt.Sprintf(`jsonrpc2: code %d message: %s: %s`, rpcCode, msg, jsonRpcErr) - var data json.RawMessage = []byte(jsonRpcErr) - c := Client{ - rpc: jsonRPCFail{ - err: &jsonrpc2.Error{ - Data: &data, - Code: int64(rpcCode), - Message: msg, - }, - }, - } - - params := map[string]interface{}{ - "test": "test", - } - err := c.Call("dummy method", params, nil) - - if err == nil { - t.Errorf("Call method should have returned non-nil error") - } - - if err.Error() != expectedErrMsg { - t.Errorf("Call method should surface property with invalid parameter. Received `%s` but expected `%s`", err, expectedErrMsg) - } -} - -func TestCall_withJsonRPC2ErrorWithNilData(t *testing.T) { - rpcCode := 10 - msg := "invalid parameters" - var expectedErrMsg string = fmt.Sprintf(`jsonrpc2: code %d message: %s`, rpcCode, msg) - c := Client{ - rpc: jsonRPCFail{ - err: &jsonrpc2.Error{ - Data: nil, - Code: int64(rpcCode), - Message: msg, - }, - }, - } - - params := map[string]interface{}{ - "test": "test", - } - err := c.Call("dummy method", params, nil) - - if err == nil { - t.Errorf("Call method should have returned non-nil error") - } - - if err.Error() != expectedErrMsg { - t.Errorf("Call method should surface property with invalid parameter. Received `%s` but expected `%s`", err, expectedErrMsg) - } -} - -func TestCall_withNonJsonRPC2Error(t *testing.T) { - expectedErr := errors.New("This is not a jsonrpc2 error") - c := Client{ - rpc: jsonRPCFail{ - err: expectedErr, - }, - } - - params := map[string]interface{}{ - "test": "test", - } - err := c.Call("dummy method", params, nil) - - if err == nil { - t.Errorf("Call method should have returned non-nil error") - } - - if err != expectedErr { - t.Errorf("Call method should return an error as is if not of type `jsonrpc2.Error`. Expected: %v received: %v", expectedErr, err) - } -} diff --git a/client/cloud_config.go b/client/cloud_config.go deleted file mode 100644 index 63b7e41f..00000000 --- a/client/cloud_config.go +++ /dev/null @@ -1,154 +0,0 @@ -package client - -import ( - "fmt" - "log" - "strings" -) - -type CloudConfig struct { - Name string `json:"name"` - Template string `json:"template"` - Id string `json:"id"` -} - -func (c CloudConfig) Compare(obj interface{}) bool { - other := obj.(CloudConfig) - - if other.Id == c.Id { - return true - } - - if other.Name == c.Name { - return true - } - - return false -} - -type CloudConfigResponse struct { - Result []CloudConfig `json:"result"` -} - -func (c *Client) GetCloudConfig(id string) (*CloudConfig, error) { - cloudConfigs, err := c.GetAllCloudConfigs() - - if err != nil { - return nil, err - } - - cloudConfig := CloudConfig{Id: id} - for _, config := range cloudConfigs { - if cloudConfig.Compare(config) { - return &config, nil - } - } - - // TODO: This should return a NotFound error (see https://github.com/terra-farm/terraform-provider-xenorchestra/issues/118) - // for more details - return nil, nil -} - -func (c *Client) GetCloudConfigByName(name string) ([]CloudConfig, error) { - allCloudConfigs, err := c.GetAllCloudConfigs() - - if err != nil { - return nil, err - } - - cloudConfigs := []CloudConfig{} - cloudConfig := CloudConfig{Name: name} - for _, config := range allCloudConfigs { - if cloudConfig.Compare(config) { - cloudConfigs = append(cloudConfigs, config) - } - } - - if len(cloudConfigs) == 0 { - return nil, NotFound{Query: CloudConfig{Name: name}} - } - return cloudConfigs, nil -} - -func (c *Client) GetAllCloudConfigs() ([]CloudConfig, error) { - var getAllResp CloudConfigResponse - params := map[string]interface{}{} - err := c.Call("cloudConfig.getAll", params, &getAllResp.Result) - - if err != nil { - return nil, err - } - return getAllResp.Result, nil -} - -func (c *Client) CreateCloudConfig(name, template string) (*CloudConfig, error) { - params := map[string]interface{}{ - "name": name, - "template": template, - } - var resp bool - err := c.Call("cloudConfig.create", params, &resp) - - if err != nil { - return nil, err - } - - // Since the Id isn't returned in the reponse loop over all cloud configs - // and find the one we just created - cloudConfigs, err := c.GetAllCloudConfigs() - - if err != nil { - return nil, err - } - - var found CloudConfig - for _, config := range cloudConfigs { - if config.Name == name && config.Template == template { - found = config - } - } - return &found, nil -} - -func (c *Client) DeleteCloudConfig(id string) error { - params := map[string]interface{}{ - "id": id, - } - var resp bool - err := c.Call("cloudConfig.delete", params, &resp) - - if err != nil { - return err - } - - return nil -} - -func RemoveCloudConfigsWithPrefix(cloudConfigPrefix string) func(string) error { - return func(_ string) error { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - return fmt.Errorf("error getting client: %s", err) - } - - cloudConfigs, err := c.GetAllCloudConfigs() - - if err != nil { - return err - } - - for _, cloudConfig := range cloudConfigs { - - if strings.HasPrefix(cloudConfig.Name, cloudConfigPrefix) { - - log.Printf("[DEBUG] Removing cloud config `%s`\n", cloudConfig.Name) - err = c.DeleteCloudConfig(cloudConfig.Id) - - if err != nil { - log.Printf("failed to remove cloud config `%s` during sweep: %v\n", cloudConfig.Name, err) - } - } - } - return nil - } -} diff --git a/client/errors.go b/client/errors.go deleted file mode 100644 index bcfb4c42..00000000 --- a/client/errors.go +++ /dev/null @@ -1,13 +0,0 @@ -package client - -import ( - "fmt" -) - -type NotFound struct { - Query XoObject -} - -func (e NotFound) Error() string { - return fmt.Sprintf("Could not find %[1]T with query: %+[1]v", e.Query) -} diff --git a/client/errors_test.go b/client/errors_test.go deleted file mode 100644 index 2fabdb3e..00000000 --- a/client/errors_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package client - -import ( - "fmt" - "testing" -) - -func TestNotFoundErrorMessage(t *testing.T) { - vif := VIF{ - MacAddress: "E8:61:7E:8E:F1:81", - } - err := NotFound{ - Query: vif, - } - - expectedMsg := fmt.Sprintf("Could not find client.VIF with query: %+v", vif) - msg := err.Error() - - if expectedMsg != msg { - t.Errorf("NotFound Error() message expected to be '%s' but received '%s'", expectedMsg, msg) - } -} diff --git a/client/go.mod b/client/go.mod deleted file mode 100644 index 43ce546d..00000000 --- a/client/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/ddelnano/terraform-provider-xenorchestra/client - -go 1.16 - -require ( - github.com/gorilla/websocket v1.4.2 - github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750 -) diff --git a/client/go.sum b/client/go.sum deleted file mode 100644 index 4b47ceef..00000000 --- a/client/go.sum +++ /dev/null @@ -1,5 +0,0 @@ -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750 h1:j3HKQAXXj5vV3oHyg9pjK3uIM4bidukvv+tR2iJCvFA= -github.com/sourcegraph/jsonrpc2 v0.0.0-20210201082850-366fbb520750/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo= diff --git a/client/host.go b/client/host.go deleted file mode 100644 index 3a2df6d0..00000000 --- a/client/host.go +++ /dev/null @@ -1,123 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "os" - "sort" -) - -type Host struct { - Id string `json:"id"` - NameLabel string `json:"name_label"` - Tags []interface{} `json:"tags,omitempty"` - Pool string `json:"$pool"` - Memory HostMemoryObject `json:"memory"` - Cpus CpuInfo `json:"cpus"` -} - -type HostMemoryObject struct { - Usage int `json:"usage"` - Size int `json:"size"` -} - -func (h Host) Compare(obj interface{}) bool { - otherHost := obj.(Host) - if otherHost.Id == h.Id { - return true - } - if h.Pool == otherHost.Pool { - return true - } - if h.NameLabel != "" && h.NameLabel == otherHost.NameLabel { - return true - } - return false -} - -func (c *Client) GetHostByName(nameLabel string) (hosts []Host, err error) { - obj, err := c.FindFromGetAllObjects(Host{NameLabel: nameLabel}) - if err != nil { - return - } - return obj.([]Host), nil -} - -func (c *Client) GetHostById(id string) (host Host, err error) { - obj, err := c.FindFromGetAllObjects(Host{Id: id}) - if err != nil { - return - } - hosts, ok := obj.([]Host) - - if !ok { - return host, errors.New("failed to coerce response into Host slice") - } - - if len(hosts) != 1 { - return host, errors.New(fmt.Sprintf("expected a single host to be returned, instead received: %d in the response: %v", len(hosts), obj)) - } - - return hosts[0], nil -} - -func FindHostForTests(hostId string, host *Host) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v", err) - os.Exit(-1) - } - - queriedHost, err := c.GetHostById(hostId) - - if err != nil { - fmt.Printf("failed to find a host with id: %v with error: %v\n", hostId, err) - os.Exit(-1) - } - - *host = queriedHost -} - -func (c *Client) GetSortedHosts(host Host, sortBy, sortOrder string) (hosts []Host, err error) { - obj, err := c.FindFromGetAllObjects(host) - - if err != nil { - return - } - slice := obj.([]Host) - - return sortHostsByField(slice, sortBy, sortOrder), nil -} - -const ( - sortOrderAsc = "asc" - sortOrderDesc = "desc" - sortFieldId = "id" - sortFieldNameLabel = "name_label" -) - -func sortHostsByField(hosts []Host, by, order string) []Host { - if by == "" || order == "" { - return hosts - } - sort.Slice(hosts, func(i, j int) bool { - switch order { - case sortOrderAsc: - return sortByField(hosts, by, i, j) - case sortOrderDesc: - return sortByField(hosts, by, j, i) - } - return false - }) - return hosts -} - -func sortByField(hosts []Host, field string, i, j int) bool { - switch field { - case sortFieldNameLabel: - return hosts[i].NameLabel < hosts[j].NameLabel - case sortFieldId: - return hosts[i].Id < hosts[j].Id - } - return false -} diff --git a/client/host_test.go b/client/host_test.go deleted file mode 100644 index ac6ad50b..00000000 --- a/client/host_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package client - -import ( - "reflect" - "testing" -) - -func TestHostCompare(t *testing.T) { - tests := []struct { - other Host - host Host - result bool - }{ - { - other: Host{ - Id: "788e1dce-44f6-4db7-ae62-185c69fecd3b", - NameLabel: "xcp-host1-k8s.domain.eu", - Pool: "pool id", - }, - host: Host{NameLabel: "xcp-host1-k8s.domain.eu"}, - result: true, - }, - { - other: Host{ - Id: "788e1dce-44f6-4db7-ae62-185c69fecd3b", - NameLabel: "xcp-host2-k8s.domain.eu", - Pool: "pool id", - }, - host: Host{NameLabel: "xcp-host1-k8s.domain.eu"}, - result: false, - }, - } - - for _, test := range tests { - host := test.host - other := test.other - result := test.result - if host.Compare(other) != result { - t.Errorf("Expected Host %v to Compare %t to %v", host, result, other) - } - } -} - -func TestGetHostByName(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - nameLabel := accTestHost.NameLabel - hosts, err := c.GetHostByName(nameLabel) - if err != nil { - t.Fatalf("failed to get host with error: %v", err) - } - - host := hosts[0] - if host.NameLabel != nameLabel { - t.Errorf("expected host to have name `%s` received `%s` instead.", nameLabel, host.NameLabel) - } - -} - -func TestGetSortedHosts(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - poolName := accTestHost.Pool - hosts, err := c.GetSortedHosts(Host{Pool: poolName}, "id", "asc") - if err != nil { - t.Fatalf("failed to get host with error: %v", err) - } - if len(hosts) == 0 { - t.Errorf("failed to find any host for pool `%s`.", poolName) - } - if len(hosts) > 1 { - if hosts[0].Id > hosts[1].Id { - t.Errorf("failed to sort hosts. expected %s to be smaller than %s.", hosts[0].Id, hosts[1].Id) - } - } - for _, host := range hosts { - if host.Pool != poolName { - t.Errorf("expected pool to have name `%s` received `%s` instead.", poolName, host.Pool) - } - } -} - -func Test_sortHostsByField(t *testing.T) { - type args struct { - hosts []Host - by string - order string - } - tests := []struct { - name string - args args - want []Host - }{ - {name: "sortIdAsc", args: args{hosts: []Host{{Id: "acb"}, {Id: "abc"}}, order: "asc", by: "id"}, want: []Host{{Id: "abc"}, {Id: "acb"}}}, - {name: "sortIdDesc", args: args{hosts: []Host{{Id: "acb"}, {Id: "abc"}}, order: "desc", by: "id"}, want: []Host{{Id: "acb"}, {Id: "abc"}}}, - {name: "sortWrongOrder", args: args{hosts: []Host{{Id: "acb"}, {Id: "abc"}}, order: "TRASH", by: "id"}, want: []Host{{Id: "acb"}, {Id: "abc"}}}, - {name: "sortWrongField", args: args{hosts: []Host{{Id: "acb"}, {Id: "abc"}, {Id: "xyz"}}, order: "asc", by: "UNKNOWN"}, want: []Host{{Id: "acb"}, {Id: "abc"}, {Id: "xyz"}}}, - {name: "sortNameLabelAsc", args: args{hosts: []Host{{NameLabel: "acb"}, {NameLabel: "abc"}, {NameLabel: "xyz"}}, order: "asc", by: "name_label"}, want: []Host{{NameLabel: "abc"}, {NameLabel: "acb"}, {NameLabel: "xyz"}}}, - {name: "noSort", args: args{hosts: []Host{{Id: "1", NameLabel: "xyz"}, {Id: "2", NameLabel: "acb"}, {Id: "3", NameLabel: "abc"}}, order: "", by: ""}, want: []Host{{Id: "1", NameLabel: "xyz"}, {Id: "2", NameLabel: "acb"}, {Id: "3", NameLabel: "abc"}}}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := sortHostsByField(tt.args.hosts, tt.args.by, tt.args.order); !reflect.DeepEqual(got, tt.want) { - t.Errorf("sortHostsByField() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/client/network.go b/client/network.go deleted file mode 100644 index 08302dea..00000000 --- a/client/network.go +++ /dev/null @@ -1,138 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "log" - "os" - "strings" -) - -type Network struct { - Id string `json:"id"` - NameLabel string `json:"name_label"` - Bridge string `json:"bridge"` - PoolId string `json:"$poolId"` -} - -func (net Network) Compare(obj interface{}) bool { - otherNet := obj.(Network) - if net.Id == otherNet.Id { - return true - } - - labelsMatch := false - if net.NameLabel == otherNet.NameLabel { - labelsMatch = true - } - - if net.PoolId == "" && labelsMatch { - return true - } else if net.PoolId == otherNet.PoolId && labelsMatch { - return true - } - - return false -} - -func (c *Client) CreateNetwork(netReq Network) (*Network, error) { - var id string - params := map[string]interface{}{ - "pool": netReq.PoolId, - "name": netReq.NameLabel, - } - - err := c.Call("network.create", params, &id) - - if err != nil { - return nil, err - } - return c.GetNetwork(Network{Id: id}) -} - -func (c *Client) GetNetwork(netReq Network) (*Network, error) { - obj, err := c.FindFromGetAllObjects(netReq) - - if err != nil { - return nil, err - } - - nets := obj.([]Network) - - if len(nets) > 1 { - return nil, errors.New(fmt.Sprintf("Your query returned more than one result: %+v. Use `pool_id` or other fields to filter the result down to a single network", nets)) - } - - return &nets[0], nil -} - -func (c *Client) GetNetworks() ([]Network, error) { - var response map[string]Network - err := c.GetAllObjectsOfType(Network{}, &response) - - nets := make([]Network, 0, len(response)) - for _, net := range response { - nets = append(nets, net) - } - return nets, err -} - -func (c *Client) DeleteNetwork(id string) error { - var success bool - params := map[string]interface{}{ - "id": id, - } - - err := c.Call("network.delete", params, &success) - - return err -} - -func RemoveNetworksWithNamePrefix(prefix string) func(string) error { - return func(_ string) error { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - return fmt.Errorf("error getting client: %s", err) - } - - nets, err := c.GetNetworks() - - if err != nil { - return err - } - - for _, net := range nets { - if strings.HasPrefix(net.NameLabel, prefix) { - log.Printf("[DEBUG] Deleting network: %v\n", net) - err = c.DeleteNetwork(net.Id) - - if err != nil { - log.Printf("error destroying network `%s` during sweep: %v", net.NameLabel, err) - } - } - } - return nil - } -} - -func FindNetworkForTests(poolId string, network *Network) { - netName, found := os.LookupEnv("XOA_NETWORK") - - if !found { - fmt.Println("The XOA_NETWORK environment variable must be set") - os.Exit(-1) - } - - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v", err) - os.Exit(-1) - } - - net, err := c.GetNetwork(Network{ - PoolId: poolId, - NameLabel: netName, - }) - - *network = *net -} diff --git a/client/network_test.go b/client/network_test.go deleted file mode 100644 index 9ba449e7..00000000 --- a/client/network_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package client - -import "testing" - -var testNetworkName string = integrationTestPrefix + "network" - -func TestNetworkCompare(t *testing.T) { - - nameLabel := "network label" - poolId := "pool id" - cases := []struct { - net Network - result bool - other Network - }{ - { - net: Network{ - NameLabel: nameLabel, - }, - result: true, - other: Network{ - Id: "355ee47d-ff4c-4924-3db2-fd86ae629676", - NameLabel: nameLabel, - PoolId: "355ee47d-ff4c-4924-3db2-fd86ae629676", - }, - }, - { - net: Network{ - NameLabel: nameLabel, - PoolId: poolId, - }, - result: false, - other: Network{ - Id: "355ee47d-ff4c-4924-3db2-fd86ae629676", - NameLabel: "name_label", - PoolId: "355ee47d-ff4c-4924-3db2-fd86ae629676", - }, - }, - { - net: Network{ - NameLabel: nameLabel, - PoolId: poolId, - }, - result: true, - other: Network{ - Id: "355ee47d-ff4c-4924-3db2-fd86ae629676", - NameLabel: nameLabel, - PoolId: poolId, - }, - }, - } - - for _, test := range cases { - net := test.net - other := test.other - result := test.result - - if net.Compare(other) != result { - t.Errorf("expected network `%+v` to Compare '%t' with other `%v`", net, result, other) - } - } -} - -func TestGetNetwork(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - net, err := c.GetNetwork(Network{ - NameLabel: testNetworkName, - }) - - if err != nil { - t.Fatalf("failed to retrieve network `%s` with error: %v", testNetworkName, err) - } - - if net == nil { - t.Fatalf("should have received network, instead received nil") - } - - if net.NameLabel != testNetworkName { - t.Errorf("expected network name_label `%s` to match `%s`", net.NameLabel, testNetworkName) - } - - if net.Bridge == "" { - t.Errorf("expected network bridge to not be an empty string") - } - - if net.PoolId == "" { - t.Errorf("expected network pool id to not be an empty string") - } -} diff --git a/client/pif.go b/client/pif.go deleted file mode 100644 index 2c6c5099..00000000 --- a/client/pif.go +++ /dev/null @@ -1,60 +0,0 @@ -package client - -import ( - "errors" -) - -type PIF struct { - Device string `json:"device"` - Host string `json:"$host"` - Network string `json:"$network"` - Id string `json:"id"` - Uuid string `json:"uuid"` - PoolId string `json:"$poolId"` - Attached bool `json:"attached"` - Vlan int `json:"vlan"` -} - -func (p PIF) Compare(obj interface{}) bool { - otherPif := obj.(PIF) - - hostIdExists := p.Host != "" - if hostIdExists && p.Host != otherPif.Host { - return false - } - - if p.Vlan == otherPif.Vlan && p.Device == otherPif.Device { - return true - } - return false -} - -func (c *Client) GetPIFByDevice(dev string, vlan int) ([]PIF, error) { - obj, err := c.FindFromGetAllObjects(PIF{Device: dev, Vlan: vlan}) - - if err != nil { - return []PIF{}, err - } - pifs, ok := obj.([]PIF) - - if !ok { - return pifs, errors.New("failed to coerce response into PIF slice") - } - - return pifs, nil -} - -func (c *Client) GetPIF(pifReq PIF) (pifs []PIF, err error) { - obj, err := c.FindFromGetAllObjects(pifReq) - - if err != nil { - return - } - pifs, ok := obj.([]PIF) - - if !ok { - return pifs, errors.New("failed to coerce response into PIF slice") - } - - return pifs, nil -} diff --git a/client/pif_test.go b/client/pif_test.go deleted file mode 100644 index 77609a7c..00000000 --- a/client/pif_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package client - -import ( - "testing" -) - -func TestGetPIFByDevice(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Errorf("failed to create client with error: %v", err) - } - - device := "eth0" - vlan_id := -1 - pifs, err := c.GetPIFByDevice(device, vlan_id) - - if err != nil { - t.Fatalf("failed to find PIF with device: %s with error: %v", device, err) - } - - pif := pifs[0] - - if pif.Device != device { - t.Errorf("PIF's device %s should have matched %s", pif.Device, device) - } - - if pif.Vlan != vlan_id { - t.Errorf("PIF's vlan %d should have matched %d", pif.Vlan, vlan_id) - } -} diff --git a/client/pool.go b/client/pool.go deleted file mode 100644 index 6a686ff4..00000000 --- a/client/pool.go +++ /dev/null @@ -1,81 +0,0 @@ -package client - -import ( - "fmt" - "os" -) - -type Pool struct { - Id string `json:"id"` - NameLabel string `json:"name_label"` - Description string `json:"name_description"` - Cpus CpuInfo `json:"cpus"` - DefaultSR string `json:"default_SR"` - Master string `json:"master"` -} - -type CpuInfo struct { - Cores int64 `json:"cores,float64` - Sockets int64 `json:"sockets,float64` -} - -func (p Pool) Compare(obj interface{}) bool { - otherPool := obj.(Pool) - - if otherPool.Id == p.Id { - return true - } - - if otherPool.NameLabel != p.NameLabel { - return false - } - return true -} - -func (c *Client) GetPoolByName(name string) (pools []Pool, err error) { - obj, err := c.FindFromGetAllObjects(Pool{NameLabel: name}) - if err != nil { - return - } - pools = obj.([]Pool) - - return pools, nil -} - -func (c *Client) GetPools(pool Pool) (pools []Pool, err error) { - obj, err := c.FindFromGetAllObjects(pool) - if err != nil { - return - } - pools = obj.([]Pool) - - return pools, nil -} - -func FindPoolForTests(pool *Pool) { - poolName, found := os.LookupEnv("XOA_POOL") - - if !found { - fmt.Println("The XOA_POOL environment variable must be set") - os.Exit(-1) - } - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v", err) - os.Exit(-1) - } - - pools, err := c.GetPoolByName(poolName) - - if err != nil { - fmt.Printf("failed to find a pool with name: %v with error: %v\n", poolName, err) - os.Exit(-1) - } - - if len(pools) != 1 { - fmt.Printf("Found %d pools with name_label %s. Please use a label that is unique so tests are reproducible.\n", len(pools), poolName) - os.Exit(-1) - } - - *pool = pools[0] -} diff --git a/client/pool_test.go b/client/pool_test.go deleted file mode 100644 index 2e44036b..00000000 --- a/client/pool_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package client - -import "testing" - -func TestPoolCompare(t *testing.T) { - tests := []struct { - other Pool - pool Pool - result bool - }{ - { - other: Pool{ - Id: "sample pool id", - NameLabel: "xenserver-ddelnano", - }, - pool: Pool{NameLabel: "xenserver-ddelnano"}, - result: true, - }, - { - other: Pool{ - Id: "sample pool id", - NameLabel: "does not match", - }, - pool: Pool{NameLabel: "xenserver-ddelnano"}, - result: false, - }, - } - - for _, test := range tests { - pool := test.pool - other := test.other - result := test.result - if pool.Compare(other) != result { - t.Errorf("Expected Pool %v to Compare %t to %v", pool, result, other) - } - } -} - -func TestGetPoolByName(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Errorf("failed to create client with error: %v", err) - } - - nameLabel := accTestPool.NameLabel - pools, err := c.GetPoolByName(nameLabel) - - pool := pools[0] - - if err != nil { - t.Errorf("failed to get pool with error: %v", err) - } - - if pool.NameLabel != nameLabel { - t.Errorf("expected pool to have name `%s` received `%s` instead.", nameLabel, pool.NameLabel) - } - - if pool.Cpus.Cores == 0 { - t.Errorf("expected pool cpu cores to be set") - } - - if pool.Cpus.Sockets == 0 { - t.Errorf("expected pool cpu sockets to be set") - } -} diff --git a/client/resource_set.go b/client/resource_set.go deleted file mode 100644 index 3fe53fc6..00000000 --- a/client/resource_set.go +++ /dev/null @@ -1,253 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "log" - "strings" -) - -type ResourceSet struct { - Id string `json:"id"` - Limits ResourceSetLimits `json:"limits"` - Name string `json:"name"` - Subjects []string `json:"subjects"` - Objects []string `json:"objects"` -} - -type ResourceSetLimits struct { - Cpus ResourceSetLimit `json:"cpus,omitempty"` - Memory ResourceSetLimit `json:"memory,omitempty"` - Disk ResourceSetLimit `json:"disk,omitempty"` -} - -type ResourceSetLimit struct { - Available int `json:"available,omitempty"` - Total int `json:"total,omitempty"` -} - -func (rs ResourceSet) Compare(obj interface{}) bool { - other := obj.(ResourceSet) - if other.Id == rs.Id { - return true - } - - if other.Name == rs.Name { - return true - } - - return false -} - -func (c Client) GetResourceSets() ([]ResourceSet, error) { - return c.makeResourceSetGetAllCall() -} - -func (c Client) GetResourceSetById(id string) (*ResourceSet, error) { - resourceSets, err := c.GetResourceSet(ResourceSet{ - Id: id, - }) - - if err != nil { - return nil, err - } - - l := len(resourceSets) - if l != 1 { - return nil, errors.New(fmt.Sprintf("found %d resource set(s) with id `%s`: %v", l, id, resourceSets)) - } - - return &resourceSets[0], nil -} - -func (c Client) GetResourceSet(rsReq ResourceSet) ([]ResourceSet, error) { - resourceSets, err := c.makeResourceSetGetAllCall() - - if err != nil { - return nil, err - } - rsRv := []ResourceSet{} - found := false - for _, rs := range resourceSets { - if rs.Compare(rsReq) { - rsRv = append(rsRv, rs) - found = true - } - } - - if !found { - return rsRv, NotFound{Query: rsReq} - } - - return rsRv, nil -} - -func (c Client) makeResourceSetGetAllCall() ([]ResourceSet, error) { - - var res struct { - ResourceSets []ResourceSet `json:"-"` - } - params := map[string]interface{}{ - "id": "dummy", - } - err := c.Call("resourceSet.getAll", params, &res.ResourceSets) - log.Printf("[DEBUG] Calling resourceSet.getAll received response: %+v with error: %v\n", res, err) - - if err != nil { - return nil, err - } - - return res.ResourceSets, nil -} - -func createLimitsMap(rsl ResourceSetLimits) map[string]interface{} { - rv := map[string]interface{}{} - - if rsl.Cpus.Total != 0 { - rv["cpus"] = rsl.Cpus - } - if rsl.Disk.Total != 0 { - rv["disk"] = rsl.Disk - } - if rsl.Memory.Total != 0 { - rv["memory"] = rsl.Memory - } - return rv -} - -func (c Client) CreateResourceSet(rsReq ResourceSet) (*ResourceSet, error) { - rs := ResourceSet{} - limits := createLimitsMap(rsReq.Limits) - params := map[string]interface{}{ - "name": rsReq.Name, - "subjects": rsReq.Subjects, - "objects": rsReq.Objects, - "limits": limits, - } - err := c.Call("resourceSet.create", params, &rs) - log.Printf("[DEBUG] Calling resourceSet.create with params: %v returned: %+v with error: %v\n", params, rs, err) - - if err != nil { - return nil, err - } - - return &rs, err -} - -func (c Client) DeleteResourceSet(rsReq ResourceSet) error { - - id := rsReq.Id - if id == "" { - rs, err := c.GetResourceSet(rsReq) - - if err != nil { - return err - } - - if len(rs) > 1 { - return errors.New(fmt.Sprintf("refusing to delete resource set since `%d` resource sets were returned: %v", len(rs), rs)) - } - - id = rs[0].Id - } - var success bool - params := map[string]interface{}{ - "id": id, - } - err := c.Call("resourceSet.delete", params, &success) - log.Printf("[DEBUG] Calling resourceSet.delete call successful: %t with error: %v\n", success, err) - - return err -} - -func (c Client) RemoveResourceSetSubject(rsReq ResourceSet, subject string) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "subject": subject, - } - var success bool - err := c.Call("resourceSet.removeSubject", params, &success) - log.Printf("[DEBUG] Calling resourceSet.removeSubject call successful: %t with error: %v\n", success, err) - return err -} - -func (c Client) AddResourceSetSubject(rsReq ResourceSet, subject string) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "subject": subject, - } - var success bool - err := c.Call("resourceSet.addSubject", params, &success) - log.Printf("[DEBUG] Calling resourceSet.addSubject call successful: %t with error: %v\n", success, err) - return err -} - -func (c Client) RemoveResourceSetObject(rsReq ResourceSet, object string) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "object": object, - } - var success bool - err := c.Call("resourceSet.removeObject", params, &success) - log.Printf("[DEBUG] Calling resourceSet.removeObject call successful: %t with error: %v\n", success, err) - return err -} - -func (c Client) AddResourceSetObject(rsReq ResourceSet, object string) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "object": object, - } - var success bool - err := c.Call("resourceSet.addObject", params, &success) - log.Printf("[DEBUG] Calling resourceSet.addObject call successful: %t with error: %v\n", success, err) - return err -} - -func (c Client) RemoveResourceSetLimit(rsReq ResourceSet, limit string) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "limitId": limit, - } - var success bool - err := c.Call("resourceSet.removeLimit", params, &success) - log.Printf("[DEBUG] Calling resourceSet.removeLimit call successful: %t with error: %v\n", success, err) - return err -} - -func (c Client) AddResourceSetLimit(rsReq ResourceSet, limit string, quantity int) error { - params := map[string]interface{}{ - "id": rsReq.Id, - "limitId": limit, - "quantity": quantity, - } - var success bool - err := c.Call("resourceSet.addLimit", params, &success) - log.Printf("[DEBUG] Calling resourceSet.addLimit call with params: %v successful: %t with error: %v\n", params, success, err) - return err -} - -func RemoveResourceSetsWithNamePrefix(rsNamePrefix string) func(string) error { - return func(_ string) error { - fmt.Println("[DEBUG] Running sweeper") - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - return fmt.Errorf("error getting client: %s", err) - } - - rss, err := c.GetResourceSets() - if err != nil { - return fmt.Errorf("error getting resource sets: %s", err) - } - for _, rs := range rss { - if strings.HasPrefix(rs.Name, rsNamePrefix) { - err := c.DeleteResourceSet(ResourceSet{Id: rs.Id}) - - if err != nil { - log.Printf("error destroying resource set `%s` during sweep: %s", rs.Name, err) - } - } - } - return nil - } -} diff --git a/client/resource_set_test.go b/client/resource_set_test.go deleted file mode 100644 index 84b9af1b..00000000 --- a/client/resource_set_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package client - -import ( - "testing" -) - -var testResourceSetName string = "xenorchestra-client-resource-set2" - -var testResourceSet = ResourceSet{ - Name: testResourceSetName, - Limits: ResourceSetLimits{ - Cpus: ResourceSetLimit{ - Total: 1, - Available: 2, - }, - Disk: ResourceSetLimit{ - Total: 1, - Available: 2, - }, - Memory: ResourceSetLimit{ - Total: 1, - Available: 2, - }, - }, - Subjects: []string{}, - Objects: []string{}, -} - -var resourceSetObj = map[string]interface{}{ - "id": "id of resource set", - "name": "resource set name", - "limits": map[string]interface{}{ - "cpus": map[string]interface{}{ - "available": 4, - "total": 4, - }, - "disk": map[string]interface{}{ - "available": 4, - "total": 4, - }, - "memory": map[string]interface{}{ - "available": 4, - "total": 4, - }, - }, -} - -func TestGetResourceSet(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - resourceSets, err := c.GetResourceSet(ResourceSet{ - Name: testResourceSetName, - }) - - if err != nil { - t.Fatalf("failed to retrieve ResourceSet with error: %v", err) - } - - rs := resourceSets[0] - - if rs.Name != testResourceSetName { - t.Errorf("resource set's name `%s` did not match expected `%s`", rs.Name, testResourceSetName) - } - - if rs.Limits.Cpus.Available != 2 { - t.Errorf("resource set should have contained 2 CPUs") - } -} diff --git a/client/setup_test.go b/client/setup_test.go deleted file mode 100644 index 27acc83c..00000000 --- a/client/setup_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package client - -import ( - "os" - "testing" -) - -func CreateResourceSet(rs ResourceSet) error { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - return err - } - _, err = c.CreateResourceSet(rs) - return err -} - -func CreateNetwork(network *Network) error { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - return err - } - - net, err := c.CreateNetwork(Network{ - NameLabel: testNetworkName, - PoolId: accTestPool.Id, - }) - - if err != nil { - return err - } - *network = *net - return nil -} - -var integrationTestPrefix string = "xenorchestra-client-" -var accTestPool Pool -var accTestHost Host -var accDefaultSr StorageRepository -var accDefaultNetwork Network -var testTemplate Template -var disklessTestTemplate Template -var accVm Vm - -func TestMain(m *testing.M) { - FindPoolForTests(&accTestPool) - FindTemplateForTests(&testTemplate, accTestPool.Id, "XOA_TEMPLATE") - FindTemplateForTests(&disklessTestTemplate, accTestPool.Id, "XOA_DISKLESS_TEMPLATE") - FindHostForTests(accTestPool.Master, &accTestHost) - FindStorageRepositoryForTests(accTestPool, &accDefaultSr, integrationTestPrefix) - CreateNetwork(&accDefaultNetwork) - FindOrCreateVmForTests(&accVm, accTestPool.Id, accDefaultSr.Id, testTemplate.Id, integrationTestPrefix) - CreateResourceSet(testResourceSet) - - code := m.Run() - - RemoveResourceSetsWithNamePrefix(integrationTestPrefix)("") - RemoveNetworksWithNamePrefix(integrationTestPrefix)("") - - os.Exit(code) -} diff --git a/client/state.go b/client/state.go deleted file mode 100644 index c981100c..00000000 --- a/client/state.go +++ /dev/null @@ -1,343 +0,0 @@ -package client - -// This file is copied from the -// github.com/hashicorp/terraform-plugin-sdk/helper/resource -// package. In order for this client to work with github.com/GoogleCloudPlatform/terraformer -// the terraform sdk cannot be used otherwise some package initialization code causes a runtime crash. -// See https://github.com/ddelnano/terraformer/commit/03999bce04c47c95957b2d569307c3ab9e80763f#comments -// for more details. - -// Ideally the xenorchestra client code would be completely decoupled from terraform and so this approach -// will likely need to be reconsidered - -import ( - "fmt" - "log" - "strings" - "time" -) - -var refreshGracePeriod = 30 * time.Second - -// StateRefreshFunc is a function type used for StateChangeConf that is -// responsible for refreshing the item being watched for a state change. -// -// It returns three results. `result` is any object that will be returned -// as the final object after waiting for state change. This allows you to -// return the final updated object, for example an EC2 instance after refreshing -// it. -// -// `state` is the latest state of that object. And `err` is any error that -// may have happened while refreshing the state. -type StateRefreshFunc func() (result interface{}, state string, err error) - -// StateChangeConf is the configuration struct used for `WaitForState`. -type StateChangeConf struct { - Delay time.Duration // Wait this time before starting checks - Pending []string // States that are "allowed" and will continue trying - Refresh StateRefreshFunc // Refreshes the current state - Target []string // Target state - Timeout time.Duration // The amount of time to wait before timeout - MinTimeout time.Duration // Smallest time to wait before refreshes - PollInterval time.Duration // Override MinTimeout/backoff and only poll this often - NotFoundChecks int // Number of times to allow not found - - // This is to work around inconsistent APIs - ContinuousTargetOccurence int // Number of times the Target state has to occur continuously -} - -// WaitForState watches an object and waits for it to achieve the state -// specified in the configuration using the specified Refresh() func, -// waiting the number of seconds specified in the timeout configuration. -// -// If the Refresh function returns an error, exit immediately with that error. -// -// If the Refresh function returns a state other than the Target state or one -// listed in Pending, return immediately with an error. -// -// If the Timeout is exceeded before reaching the Target state, return an -// error. -// -// Otherwise, the result is the result of the first call to the Refresh function to -// reach the target state. -func (conf *StateChangeConf) WaitForState() (interface{}, error) { - log.Printf("[DEBUG] Waiting for state to become: %s", conf.Target) - - notfoundTick := 0 - targetOccurence := 0 - - // Set a default for times to check for not found - if conf.NotFoundChecks == 0 { - conf.NotFoundChecks = 20 - } - - if conf.ContinuousTargetOccurence == 0 { - conf.ContinuousTargetOccurence = 1 - } - - type Result struct { - Result interface{} - State string - Error error - Done bool - } - - // Read every result from the refresh loop, waiting for a positive result.Done. - resCh := make(chan Result, 1) - // cancellation channel for the refresh loop - cancelCh := make(chan struct{}) - - result := Result{} - - go func() { - defer close(resCh) - - time.Sleep(conf.Delay) - - // start with 0 delay for the first loop - var wait time.Duration - - for { - // store the last result - resCh <- result - - // wait and watch for cancellation - select { - case <-cancelCh: - return - case <-time.After(wait): - // first round had no wait - if wait == 0 { - wait = 100 * time.Millisecond - } - } - - res, currentState, err := conf.Refresh() - result = Result{ - Result: res, - State: currentState, - Error: err, - } - - if err != nil { - resCh <- result - return - } - - // If we're waiting for the absence of a thing, then return - if res == nil && len(conf.Target) == 0 { - targetOccurence++ - if conf.ContinuousTargetOccurence == targetOccurence { - result.Done = true - resCh <- result - return - } - continue - } - - if res == nil { - // If we didn't find the resource, check if we have been - // not finding it for awhile, and if so, report an error. - notfoundTick++ - if notfoundTick > conf.NotFoundChecks { - result.Error = &NotFoundError{ - LastError: err, - Retries: notfoundTick, - } - resCh <- result - return - } - } else { - // Reset the counter for when a resource isn't found - notfoundTick = 0 - found := false - - for _, allowed := range conf.Target { - if currentState == allowed { - found = true - targetOccurence++ - if conf.ContinuousTargetOccurence == targetOccurence { - result.Done = true - resCh <- result - return - } - continue - } - } - - for _, allowed := range conf.Pending { - if currentState == allowed { - found = true - targetOccurence = 0 - break - } - } - - if !found && len(conf.Pending) > 0 { - result.Error = &UnexpectedStateError{ - LastError: err, - State: result.State, - ExpectedState: conf.Target, - } - resCh <- result - return - } - } - - // Wait between refreshes using exponential backoff, except when - // waiting for the target state to reoccur. - if targetOccurence == 0 { - wait *= 2 - } - - // If a poll interval has been specified, choose that interval. - // Otherwise bound the default value. - if conf.PollInterval > 0 && conf.PollInterval < 180*time.Second { - wait = conf.PollInterval - } else { - if wait < conf.MinTimeout { - wait = conf.MinTimeout - } else if wait > 10*time.Second { - wait = 10 * time.Second - } - } - - log.Printf("[TRACE] Waiting %s before next try", wait) - } - }() - - // store the last value result from the refresh loop - lastResult := Result{} - - timeout := time.After(conf.Timeout) - for { - select { - case r, ok := <-resCh: - // channel closed, so return the last result - if !ok { - return lastResult.Result, lastResult.Error - } - - // we reached the intended state - if r.Done { - return r.Result, r.Error - } - - // still waiting, store the last result - lastResult = r - - case <-timeout: - log.Printf("[WARN] WaitForState timeout after %s", conf.Timeout) - log.Printf("[WARN] WaitForState starting %s refresh grace period", refreshGracePeriod) - - // cancel the goroutine and start our grace period timer - close(cancelCh) - timeout := time.After(refreshGracePeriod) - - // we need a for loop and a label to break on, because we may have - // an extra response value to read, but still want to wait for the - // channel to close. - forSelect: - for { - select { - case r, ok := <-resCh: - if r.Done { - // the last refresh loop reached the desired state - return r.Result, r.Error - } - - if !ok { - // the goroutine returned - break forSelect - } - - // target state not reached, save the result for the - // TimeoutError and wait for the channel to close - lastResult = r - case <-timeout: - log.Println("[ERROR] WaitForState exceeded refresh grace period") - break forSelect - } - } - - return nil, &TimeoutError{ - LastError: lastResult.Error, - LastState: lastResult.State, - Timeout: conf.Timeout, - ExpectedState: conf.Target, - } - } - } -} - -type NotFoundError struct { - LastError error - LastRequest interface{} - LastResponse interface{} - Message string - Retries int -} - -func (e *NotFoundError) Error() string { - if e.Message != "" { - return e.Message - } - - if e.Retries > 0 { - return fmt.Sprintf("couldn't find resource (%d retries)", e.Retries) - } - - return "couldn't find resource" -} - -// UnexpectedStateError is returned when Refresh returns a state that's neither in Target nor Pending -type UnexpectedStateError struct { - LastError error - State string - ExpectedState []string -} - -func (e *UnexpectedStateError) Error() string { - return fmt.Sprintf( - "unexpected state '%s', wanted target '%s'. last error: %s", - e.State, - strings.Join(e.ExpectedState, ", "), - e.LastError, - ) -} - -// TimeoutError is returned when WaitForState times out -type TimeoutError struct { - LastError error - LastState string - Timeout time.Duration - ExpectedState []string -} - -func (e *TimeoutError) Error() string { - expectedState := "resource to be gone" - if len(e.ExpectedState) > 0 { - expectedState = fmt.Sprintf("state to become '%s'", strings.Join(e.ExpectedState, ", ")) - } - - extraInfo := make([]string, 0) - if e.LastState != "" { - extraInfo = append(extraInfo, fmt.Sprintf("last state: '%s'", e.LastState)) - } - if e.Timeout > 0 { - extraInfo = append(extraInfo, fmt.Sprintf("timeout: %s", e.Timeout.String())) - } - - suffix := "" - if len(extraInfo) > 0 { - suffix = fmt.Sprintf(" (%s)", strings.Join(extraInfo, ", ")) - } - - if e.LastError != nil { - return fmt.Sprintf("timeout while waiting for %s%s: %s", - expectedState, suffix, e.LastError) - } - - return fmt.Sprintf("timeout while waiting for %s%s", - expectedState, suffix) -} diff --git a/client/storage_repository.go b/client/storage_repository.go deleted file mode 100644 index ce7efcb3..00000000 --- a/client/storage_repository.go +++ /dev/null @@ -1,117 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "os" -) - -type StorageRepository struct { - Id string `json:"id"` - Uuid string `json:"uuid"` - NameLabel string `json:"name_label"` - PoolId string `json:"$poolId"` - SRType string `json:"SR_type"` - Container string `json:"$container"` - PhysicalUsage int `json:"physical_usage"` - Size int `json:"size"` - Usage int `json:"usage"` - Tags []string `json:"tags,omitempty"` -} - -func (s StorageRepository) Compare(obj interface{}) bool { - otherSr := obj.(StorageRepository) - - if s.Id != "" && s.Id == otherSr.Id { - return true - } - - if len(s.Tags) > 0 { - for _, tag := range s.Tags { - if !stringInSlice(tag, otherSr.Tags) { - return false - } - } - } - - labelsMatch := false - if s.NameLabel == otherSr.NameLabel { - labelsMatch = true - } - - if s.PoolId == "" && labelsMatch { - return true - } else if s.PoolId == otherSr.PoolId && labelsMatch { - return true - } - - return false -} - -func stringInSlice(needle string, haystack []string) bool { - for _, s := range haystack { - if s == needle { - return true - } - } - return false -} - -func (c *Client) GetStorageRepositoryById(id string) (StorageRepository, error) { - obj, err := c.FindFromGetAllObjects(StorageRepository{Id: id}) - var sr StorageRepository - - if err != nil { - return sr, err - } - srs, ok := obj.([]StorageRepository) - - if !ok { - return sr, errors.New("failed to coerce response into StorageRepository slice") - } - - if len(srs) != 1 { - return sr, errors.New(fmt.Sprintf("expected a single storage respository to be returned, instead received: %d in the response: %v", len(srs), obj)) - } - - return srs[0], nil -} - -func (c *Client) GetStorageRepository(sr StorageRepository) ([]StorageRepository, error) { - obj, err := c.FindFromGetAllObjects(sr) - - if err != nil { - return nil, err - } - srs, ok := obj.([]StorageRepository) - - if !ok { - return nil, errors.New("failed to coerce response into StorageRepository slice") - } - - return srs, nil -} - -func FindStorageRepositoryForTests(pool Pool, sr *StorageRepository, tag string) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v", err) - os.Exit(-1) - } - - defaultSr, err := c.GetStorageRepositoryById(pool.DefaultSR) - - if err != nil { - fmt.Printf("failed to find the default storage repository with id: %s with error: %v\n", pool.DefaultSR, err) - os.Exit(-1) - } - - *sr = defaultSr - - err = c.AddTag(defaultSr.Id, tag) - - if err != nil { - fmt.Printf("failed to set tag on default storage repository with id: %s with error: %v\n", pool.DefaultSR, err) - os.Exit(-1) - } -} diff --git a/client/storage_repository_test.go b/client/storage_repository_test.go deleted file mode 100644 index 442b0e49..00000000 --- a/client/storage_repository_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package client - -import ( - "testing" -) - -func TestStorageRepositoryCompare(t *testing.T) { - tests := []struct { - other StorageRepository - sr StorageRepository - result bool - }{ - { - other: StorageRepository{ - NameLabel: "Test", - PoolId: "Sample pool id", - }, - sr: StorageRepository{NameLabel: "Test"}, - result: true, - }, - { - other: StorageRepository{ - NameLabel: "Test", - PoolId: "Pool A", - }, - sr: StorageRepository{NameLabel: "Test", PoolId: "Pool A"}, - result: true, - }, - { - other: StorageRepository{ - NameLabel: "Test", - PoolId: "does not match", - }, - sr: StorageRepository{NameLabel: "Test", PoolId: "Pool A"}, - result: false, - }, - { - other: StorageRepository{ - NameLabel: "Test", - PoolId: "Pool A", - }, - sr: StorageRepository{ - NameLabel: "Test", - PoolId: "Pool A", - Tags: []string{"tag1"}, - }, - result: false, - }, - } - - for _, test := range tests { - sr := test.sr - other := test.other - result := test.result - if sr.Compare(other) != result { - t.Errorf("Expected Storage Repository %v to Compare %t to %v", sr, result, other) - } - } -} - -func TestGetStorageRepositoryByNameLabel(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - defaultSr, err := c.GetStorageRepositoryById(accTestPool.DefaultSR) - - if err != nil { - t.Fatalf("failed to retrieve storage repository by id with error: %v", err) - } - - srs, err := c.GetStorageRepository(StorageRepository{NameLabel: defaultSr.NameLabel}) - - if err != nil { - t.Fatalf("failed to get storage repository by name label with error: %v", err) - } - - sr := srs[0] - if sr.NameLabel != defaultSr.NameLabel { - t.Errorf("expected storage repository to have name `%s` received `%s` instead.", defaultSr.NameLabel, sr.NameLabel) - } -} diff --git a/client/tag.go b/client/tag.go deleted file mode 100644 index 41ed46ed..00000000 --- a/client/tag.go +++ /dev/null @@ -1,95 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "log" -) - -func (c *Client) AddTag(id, tag string) error { - var success bool - params := map[string]interface{}{ - "id": id, - "tag": tag, - } - err := c.Call("tag.add", params, &success) - - if err != nil { - return err - } - return nil -} - -func (c *Client) RemoveTag(id, tag string) error { - var success bool - params := map[string]interface{}{ - "id": id, - "tag": tag, - } - err := c.Call("tag.remove", params, &success) - - if err != nil { - return err - } - return nil -} - -type Object struct { - Id string - Type string -} - -func (c *Client) GetObjectsWithTags(tags []string) ([]Object, error) { - var objsRes struct { - Objects map[string]interface{} `json:"-"` - } - params := map[string]interface{}{ - "filter": map[string][]string{ - "tags": tags, - }, - } - c.Call("xo.getAllObjects", params, &objsRes.Objects) - log.Printf("[DEBUG] Found objects with tags `%s`: %v\n", tags, objsRes) - - t := []Object{} - for _, resObject := range objsRes.Objects { - obj, ok := resObject.(map[string]interface{}) - - if !ok { - return t, errors.New("Could not coerce interface{} into map") - } - - id := obj["id"].(string) - objType := obj["type"].(string) - t = append(t, Object{ - Id: id, - Type: objType, - }) - } - return t, nil -} - -func RemoveTagFromAllObjects(tag string) func(string) error { - return func(_ string) error { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - return fmt.Errorf("error getting client: %s", err) - } - - objects, err := c.GetObjectsWithTags([]string{tag}) - - if err != nil { - return err - } - - for _, object := range objects { - log.Printf("[DEBUG] Remove tag `%s` on object `%s`\n", tag, object) - err = c.RemoveTag(object.Id, tag) - - if err != nil { - log.Printf("error remove tag `%s` during sweep: %v", tag, err) - } - } - return nil - } -} diff --git a/client/template.go b/client/template.go deleted file mode 100644 index 04bf4079..00000000 --- a/client/template.go +++ /dev/null @@ -1,104 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "os" -) - -type TemplateDisk struct { - Bootable bool `json:"bootable"` - Device string `json:"device"` - Size int `json:"size"` - Type string `json:"type"` - SR string `json:"SR"` -} - -type TemplateInfo struct { - Arch string `json:"arch"` - Disks []TemplateDisk `json:"disks"` -} - -type Template struct { - Id string `json:"id"` - Uuid string `json:"uuid"` - NameLabel string `json:"name_label"` - PoolId string `json:"$poolId"` - TemplateInfo TemplateInfo `json:"template_info"` -} - -func (t Template) Compare(obj interface{}) bool { - other := obj.(Template) - - if t.Id == other.Id { - return true - } - - labelsMatch := false - if t.NameLabel == other.NameLabel { - labelsMatch = true - } - - if t.PoolId == "" && labelsMatch { - return true - } else if t.PoolId == other.PoolId && labelsMatch { - return true - } - return false -} - -func (t Template) isDiskTemplate() bool { - if len(t.TemplateInfo.Disks) == 0 && t.NameLabel != "Other install media" { - return true - } - - return false -} - -func (c *Client) GetTemplate(template Template) ([]Template, error) { - obj, err := c.FindFromGetAllObjects(template) - var templates []Template - if err != nil { - return templates, err - } - - templates, ok := obj.([]Template) - - if !ok { - return templates, errors.New("failed to coerce response into Template slice") - } - - return templates, nil -} - -func FindTemplateForTests(template *Template, poolId, templateEnvVar string) { - var found bool - templateName, found := os.LookupEnv(templateEnvVar) - if !found { - fmt.Println(fmt.Sprintf("The %s environment variable must be set for the tests", templateEnvVar)) - os.Exit(-1) - } - - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v", err) - os.Exit(-1) - } - - templates, err := c.GetTemplate(Template{ - NameLabel: templateName, - PoolId: poolId, - }) - - if err != nil { - fmt.Printf("failed to find templates with error: %v\n", err) - os.Exit(-1) - } - - l := len(templates) - if l != 1 { - fmt.Printf("found %d templates when expected to find 1. templates found: %v\n", l, templates) - os.Exit(-1) - } - *template = templates[0] -} diff --git a/client/template_test.go b/client/template_test.go deleted file mode 100644 index cae6b713..00000000 --- a/client/template_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package client - -import ( - "testing" -) - -func TestGetTemplate(t *testing.T) { - tests := []struct { - templateName string - template Template - err error - }{ - { - templateName: testTemplate.NameLabel, - template: Template{ - NameLabel: testTemplate.NameLabel, - }, - err: nil, - }, - { - templateName: "Not found", - template: Template{}, - err: NotFound{Query: Template{NameLabel: "Not found"}}, - }, - } - - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Errorf("failed to create client: %v", err) - } - - for _, test := range tests { - - templateName := test.templateName - templates, err := c.GetTemplate(Template{NameLabel: templateName}) - - failureMsg := "failed to get template `%s` expected err: %v received: %v" - if test.err == nil { - if test.err != err { - t.Fatalf(failureMsg, templateName, test.err, err) - } - - } else { - if test.err.Error() != err.Error() { - t.Fatalf(failureMsg, templateName, test.err, err) - } - } - - if _, ok := test.err.(NotFound); ok { - continue - } - - if len(templates) < 1 { - t.Fatalf("failed to find templates for the following name_label: %s", templateName) - } - tmp := templates[0] - if test.template.NameLabel != "" && tmp.NameLabel != templateName { - t.Errorf("template returned from xoa does not match. expected %s, found %s", tmp.NameLabel, templateName) - } - } -} diff --git a/client/user.go b/client/user.go deleted file mode 100644 index e5fa61af..00000000 --- a/client/user.go +++ /dev/null @@ -1,135 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "log" - "strings" -) - -type User struct { - Id string - Email string - Password string `json:"-"` - Groups []string - Permission string - Preferences Preferences -} - -type Preferences struct { - SshKeys []SshKey `json:"sshKeys,omitempty"` -} - -type SshKey struct { - Title string - Key string -} - -func (user User) Compare(obj interface{}) bool { - other := obj.(User) - - if user.Id == other.Id { - return true - } - - if user.Email == other.Email { - return true - } - - return false -} - -func (c *Client) CreateUser(user User) (*User, error) { - var id string - params := map[string]interface{}{ - "email": user.Email, - "password": user.Password, - } - err := c.Call("user.create", params, &id) - - if err != nil { - return nil, err - } - - return c.GetUser(User{Id: id}) -} - -func (c *Client) GetAllUsers() ([]User, error) { - params := map[string]interface{}{ - "dummy": "dummy", - } - users := []User{} - err := c.Call("user.getAll", params, &users) - - log.Printf("[DEBUG] Found the following users: %v\n", users) - if err != nil { - return nil, err - } - return users, nil -} - -func (c *Client) GetUser(userReq User) (*User, error) { - users, err := c.GetAllUsers() - if err != nil { - return nil, err - } - - var foundUser User - for _, user := range users { - if user.Compare(userReq) { - foundUser = user - } - } - - if foundUser.Id == "" { - return nil, NotFound{Query: userReq} - } - - return &foundUser, nil -} - -func (c *Client) DeleteUser(user User) error { - var success bool - params := map[string]interface{}{ - "id": user.Id, - } - err := c.Call("user.delete", params, &success) - - if err != nil { - return err - } - - if !success { - return errors.New("failed to delete user") - } - return nil -} - -func RemoveUsersWithPrefix(usernamePrefix string) func(string) error { - return func(_ string) error { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - return fmt.Errorf("error getting client: %s", err) - } - - users, err := c.GetAllUsers() - - if err != nil { - return err - } - - for _, user := range users { - - if strings.HasPrefix(user.Email, usernamePrefix) { - - log.Printf("[DEBUG] Removing user `%s`\n", user.Email) - err = c.DeleteUser(user) - - if err != nil { - log.Printf("failed to remove user `%s` during sweep: %v\n", user.Email, err) - } - } - } - return nil - } -} diff --git a/client/user_test.go b/client/user_test.go deleted file mode 100644 index fbbb5158..00000000 --- a/client/user_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package client - -import ( - "testing" -) - -func TestGetUser(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - expectedUser := User{ - Email: "ddelnano", - Password: "password", - } - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - user, err := c.CreateUser(expectedUser) - defer c.DeleteUser(*user) - - if err != nil { - t.Fatalf("failed to create user with error: %v", err) - } - - if user == nil { - t.Fatalf("expected to receive non-nil user") - } - - if user.Id == "" { - t.Errorf("expected user to have a non-empty Id") - } - - _, err = c.GetUser(User{Id: user.Id}) - - if err != nil { - t.Errorf("failed to find user by id `%s` with error: %v", user.Id, err) - } -} diff --git a/client/vdi.go b/client/vdi.go deleted file mode 100644 index c31cea75..00000000 --- a/client/vdi.go +++ /dev/null @@ -1,240 +0,0 @@ -package client - -import ( - "errors" - "fmt" -) - -type Disk struct { - VBD - VDI -} - -type VDI struct { - VDIId string `json:"id"` - SrId string `json:"$SR"` - NameLabel string `json:"name_label"` - NameDescription string `json:"name_description"` - Size int `json:"size"` - VBDs []string `json:"$VBDs"` - PoolId string `json:"$poolId"` - Tags []string `json:"tags,omitempty"` -} - -func (v VDI) Compare(obj interface{}) bool { - other := obj.(VDI) - - if v.VDIId != "" && other.VDIId == v.VDIId { - return true - } - - labelsMatch := false - if v.NameLabel == other.NameLabel { - labelsMatch = true - } - - if v.PoolId == other.PoolId && labelsMatch { - return true - } - - if len(v.Tags) > 0 { - for _, tag := range v.Tags { - if !stringInSlice(tag, other.Tags) { - return false - } - } - } - - return false -} - -// TODO: Change this file to storage or disks? -type VBD struct { - Id string `json:"id"` - Attached bool - Device string - ReadOnly bool `json:"read_only"` - VmId string `json:"VM"` - VDI string `json:"VDI"` - IsCdDrive bool `json:"is_cd_drive"` - Position string - Bootable bool - PoolId string `json:"$poolId"` -} - -func (v VBD) Compare(obj interface{}) bool { - other := obj.(VBD) - if v.IsCdDrive != other.IsCdDrive { - return false - } - - if other.VmId != "" && v.VmId == other.VmId { - return true - } - - return false -} - -func (c *Client) getDisksFromVBDs(vbd VBD) ([]Disk, error) { - obj, err := c.FindFromGetAllObjects(vbd) - - if _, ok := err.(NotFound); ok { - return []Disk{}, nil - } - - if err != nil { - return nil, err - } - disks, ok := obj.([]VBD) - - if !ok { - return []Disk{}, errors.New(fmt.Sprintf("failed to coerce %v into VBD", obj)) - } - - vdis := []Disk{} - for _, disk := range disks { - vdi, err := c.GetParentVDI(disk) - - if err != nil { - return []Disk{}, err - } - - vdis = append(vdis, Disk{disk, vdi}) - } - return vdis, nil -} - -func (c *Client) GetDisks(vm *Vm) ([]Disk, error) { - return c.getDisksFromVBDs(VBD{ - VmId: vm.Id, - IsCdDrive: false, - }) -} - -func (c *Client) GetCdroms(vm *Vm) ([]Disk, error) { - cds, err := c.getDisksFromVBDs(VBD{ - VmId: vm.Id, - IsCdDrive: true, - }) - - // Not every Vm will have CDs. Rather than pass - // this to the caller, catch it and return empty - // CDs. - if _, ok := err.(NotFound); ok { - return []Disk{}, nil - } - - return cds, err -} - -func (c *Client) GetVDIs(vdiReq VDI) ([]VDI, error) { - obj, err := c.FindFromGetAllObjects(vdiReq) - - if err != nil { - return nil, err - } - - vdis, ok := obj.([]VDI) - - if !ok { - return nil, errors.New(fmt.Sprintf("failed to coerce %+v into VDI", obj)) - } - - return vdis, nil -} - -func (c *Client) GetParentVDI(vbd VBD) (VDI, error) { - obj, err := c.FindFromGetAllObjects(VDI{ - VDIId: vbd.VDI, - }) - - // Rather than detect not found errors for finding the - // parent VDI this is considered an error so we return - // it to the caller. - if err != nil { - return VDI{}, err - } - disks, ok := obj.([]VDI) - - if !ok { - return VDI{}, errors.New(fmt.Sprintf("failed to coerce %+v into VDI", obj)) - } - - if len(disks) != 1 { - return VDI{}, errors.New(fmt.Sprintf("expected Vm VDI '%s' to only contain a single VBD, instead found %d: %+v", vbd.VDI, len(disks), disks)) - } - return disks[0], nil -} - -func (c *Client) CreateDisk(vm Vm, d Disk) (string, error) { - var id string - params := map[string]interface{}{ - "name": d.NameLabel, - "size": d.Size, - "sr": d.SrId, - "vm": vm.Id, - } - err := c.Call("disk.create", params, &id) - - return id, err -} - -func (c *Client) DeleteDisk(vm Vm, d Disk) error { - var success bool - disconnectParams := map[string]interface{}{ - "id": d.Id, - } - err := c.Call("vbd.disconnect", disconnectParams, &success) - - if err != nil { - return err - } - - vdiDeleteParams := map[string]interface{}{ - "id": d.VDIId, - } - return c.Call("vdi.delete", vdiDeleteParams, &success) -} - -func (c *Client) ConnectDisk(d Disk) error { - var success bool - params := map[string]interface{}{ - "id": d.Id, - } - return c.Call("vbd.connect", params, &success) -} - -func (c *Client) DisconnectDisk(d Disk) error { - var success bool - params := map[string]interface{}{ - "id": d.Id, - } - return c.Call("vbd.disconnect", params, &success) -} - -func (c *Client) UpdateVDI(d Disk) error { - var success bool - params := map[string]interface{}{ - "id": d.VDIId, - "name_description": d.NameDescription, - "name_label": d.NameLabel, - } - return c.Call("vdi.set", params, &success) -} - -func (c *Client) EjectCd(id string) error { - var success bool - params := map[string]interface{}{ - "id": id, - } - return c.Call("vm.ejectCd", params, &success) -} - -func (c *Client) InsertCd(vmId, cdId string) error { - var success bool - params := map[string]interface{}{ - "id": vmId, - "cd_id": cdId, - } - return c.Call("vm.insertCd", params, &success) -} diff --git a/client/vdi_test.go b/client/vdi_test.go deleted file mode 100644 index 39b05d77..00000000 --- a/client/vdi_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package client - -import ( - "fmt" - "testing" -) - -func TestGetVmDisks(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - disks, err := c.GetDisks(&accVm) - - if err != nil { - t.Fatalf("failed to get disks of VM with error: %v", err) - } - - if len(disks) <= 0 { - t.Fatalf("failed to find disks for Vm") - } - - if !validateDisk(disks[0]) { - t.Errorf("failed to validate that disks contained expected data") - } -} - -func validateDisk(disk Disk) bool { - if disk.Id == "" { - return false - } - - if disk.VBD.PoolId == "" { - return false - } - - if disk.Device == "" { - return false - } - - if disk.NameLabel == "" { - return false - } - return true -} - -func TestCreateDiskAndDeleteDisk(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - diskNameLabel := fmt.Sprintf("%stesting", integrationTestPrefix) - diskId, err := c.CreateDisk( - accVm, - Disk{ - VBD{}, - VDI{ - NameLabel: diskNameLabel, - Size: 10000, - SrId: accDefaultSr.Id, - }, - }, - ) - - if err != nil { - t.Fatalf("failed to create disk with error: %v", err) - } - - disks, err := c.GetDisks(&accVm) - - for _, disk := range disks { - if disk.NameLabel != diskNameLabel { - continue - } - - err = c.DeleteDisk(accVm, disk) - - if err != nil { - t.Errorf("failed to delete disk with id: %s with error: %v", diskId, err) - } - } -} - -func TestDisconnectDiskAndConnectDisk(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - disks, err := c.GetDisks(&accVm) - - if err != nil { - t.Fatalf("failed to retrieve disks with error: %v", err) - } - - if err := c.DisconnectDisk(disks[1]); err != nil { - t.Fatalf("failed to disconnect disk: %+v with error: %v", disks[1], err) - } - - if err := c.ConnectDisk(disks[1]); err != nil { - t.Errorf("failed to connect disk: %+v with error: %v", disks[1], err) - } -} diff --git a/client/vif.go b/client/vif.go deleted file mode 100644 index 0486dc42..00000000 --- a/client/vif.go +++ /dev/null @@ -1,148 +0,0 @@ -package client - -import ( - "errors" - "fmt" - "log" -) - -type VIF struct { - Id string `json:"id"` - Attached bool `json:"attached"` - Network string `json:"$network"` - Device string `json:"device"` - MacAddress string `json:"MAC"` - VmId string `json:"$VM"` -} - -func (v VIF) Compare(obj interface{}) bool { - other := obj.(VIF) - if v.Id == other.Id { - return true - } - - if v.MacAddress == other.MacAddress { - return true - } - - if v.VmId == other.VmId { - return true - } - return false -} - -func (c *Client) GetVIFs(vm *Vm) ([]VIF, error) { - obj, err := c.FindFromGetAllObjects(VIF{VmId: vm.Id}) - - if _, ok := err.(NotFound); ok { - return []VIF{}, nil - } - - if err != nil { - return nil, err - } - vifs, ok := obj.([]VIF) - if !ok { - return []VIF{}, errors.New("failed to coerce response into VIF slice") - } - - return vifs, nil -} - -func (c *Client) GetVIF(vifReq *VIF) (*VIF, error) { - - obj, err := c.FindFromGetAllObjects(VIF{ - Id: vifReq.Id, - MacAddress: vifReq.MacAddress, - }) - - if err != nil { - return nil, err - } - - vifs := obj.([]VIF) - - if len(vifs) > 1 { - return nil, errors.New(fmt.Sprintf("recieved %d VIFs but was expecting a single VIF to be returned", len(vifs))) - } - return &vifs[0], nil -} - -func (c *Client) CreateVIF(vm *Vm, vif *VIF) (*VIF, error) { - - var id string - params := map[string]interface{}{ - "network": vif.Network, - "vm": vm.Id, - "mac": vif.MacAddress, - } - err := c.Call("vm.createInterface", params, &id) - - if err != nil { - return nil, err - } - - return c.GetVIF(&VIF{Id: id}) -} - -func (c *Client) ConnectVIF(vifReq *VIF) (err error) { - vif, err := c.GetVIF(vifReq) - - if err != nil { - return - } - var success bool - err = c.Call("vif.connect", map[string]interface{}{ - "id": vif.Id, - }, &success) - return -} - -func (c *Client) DisconnectVIF(vifReq *VIF) (err error) { - vif, err := c.GetVIF(vifReq) - - if err != nil { - return - } - - var success bool - err = c.Call("vif.disconnect", map[string]interface{}{ - "id": vif.Id, - }, &success) - return -} - -func (c *Client) DeleteVIF(vifReq *VIF) (err error) { - var vif *VIF - - // This is a request that is looking the VIF - // up by macaddress and needs to lookup the ID first. - if vifReq.Id == "" { - vif, err = c.GetVIF(vifReq) - - if err != nil { - return err - } - } else { - vif = vifReq - } - - err = c.DisconnectVIF(vif) - - if err != nil { - return err - } - - params := map[string]interface{}{ - "id": vif.Id, - } - var result bool - err = c.Call("vif.delete", params, &result) - log.Printf("[DEBUG] Calling vif.delete received err: %v", err) - - if err != nil { - return err - } - - return nil -} diff --git a/client/vif_test.go b/client/vif_test.go deleted file mode 100644 index 9cad21f6..00000000 --- a/client/vif_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package client - -import ( - "testing" -) - -func TestGetVIFs(t *testing.T) { - - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - vifs, err := c.GetVIFs(&accVm) - - for _, vif := range vifs { - if vif.Device == "" { - t.Errorf("expecting `Device` field to be set on VIF") - } - - if vif.MacAddress == "" { - t.Errorf("expecting `MacAddress` field to be set on VIF") - } - - if vif.Network == "" { - t.Errorf("expecting `Network` field to be set on VIF") - } - - if vif.VmId != accVm.Id { - t.Errorf("VIF's VmId `%s` should have matched: %v", vif.VmId, accVm) - } - - if len(vif.Device) == 0 { - t.Errorf("expecting `Device` field to be set on VIF instead received: %s", vif.Device) - } - - // if !vif.Attached { - // t.Errorf("expecting `Attached` field to be true on VIF instead received: %t", vif.Attached) - // } - } -} - -func TestGetVIF(t *testing.T) { - - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - vifs, err := c.GetVIFs(&accVm) - - expectedVIF := vifs[0] - - vif, err := c.GetVIF(&VIF{ - MacAddress: expectedVIF.MacAddress, - }) - - if err != nil { - t.Fatalf("failed to get VIF with error: %v", err) - } - - if vif.MacAddress != expectedVIF.MacAddress { - t.Errorf("expected VIF: %v does not match the VIF we received %v", expectedVIF, vif) - } -} - -func TestCreateVIF_DeleteVIF(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - vm, err := c.GetVm(accVm) - - if err != nil { - t.Fatalf("failed to get VM with error: %v", err) - } - - vif, err := c.CreateVIF(vm, &VIF{Network: accDefaultNetwork.Id}) - - if err != nil { - t.Fatalf("failed to create VIF with error: %v", err) - } - - err = c.DeleteVIF(vif) - - if err != nil { - t.Errorf("failed to delete the VIF with error: %v", err) - } -} diff --git a/client/vm.go b/client/vm.go deleted file mode 100644 index df6f7223..00000000 --- a/client/vm.go +++ /dev/null @@ -1,569 +0,0 @@ -package client - -import ( - "encoding/json" - "errors" - "fmt" - "log" - "os" - "strconv" - "time" -) - -type allObjectResponse struct { - Objects map[string]Vm `json:"-"` -} - -type CPUs struct { - Number int `json:"number"` - Max int `json:"max"` -} - -type MemoryObject struct { - Dynamic []int `json:"dynamic"` - Static []int `json:"static"` - Size int `json:"size"` -} - -type Boot struct { - Firmware string `json:"firmware,omitempty"` -} - -// The XO api sometimes returns the videoram field as an int -// and sometimes as a string. This overrides the default json -// unmarshalling so that we can handle both of these cases -type Videoram struct { - Value int `json:"-"` -} - -func (v *Videoram) UnmarshalJSON(data []byte) (err error) { - s := string(data) - l := len(s) - if s[0] == '"' && s[l-1] == '"' { - num := 0 - if l > 2 { - num, err = strconv.Atoi(s[1 : l-1]) - - if err != nil { - return err - } - - } - v.Value = num - return nil - } - - return json.Unmarshal(data, &v.Value) -} - -type Vm struct { - Addresses map[string]string `json:"addresses,omitempty"` - BlockedOperations map[string]string `json:"blockedOperations,omitempty"` - Boot Boot `json:"boot,omitempty"` - Type string `json:"type,omitempty"` - Id string `json:"id,omitempty"` - AffinityHost string `json:"affinityHost,omitempty"` - NameDescription string `json:"name_description"` - NameLabel string `json:"name_label"` - CPUs CPUs `json:"CPUs"` - ExpNestedHvm bool `json:"expNestedHvm,omitempty"` - Memory MemoryObject `json:"memory"` - PowerState string `json:"power_state"` - VIFs []string `json:"VIFs"` - VBDs []string `json:"$VBDs"` - VirtualizationMode string `json:"virtualizationMode"` - PoolId string `json:"$poolId"` - Template string `json:"template"` - AutoPoweron bool `json:"auto_poweron"` - HA string `json:"high_availability"` - CloudConfig string `json:"cloudConfig"` - ResourceSet string `json:"resourceSet,omitempty"` - // TODO: (#145) Uncomment this once issues with secure_boot have been figured out - // SecureBoot bool `json:"secureBoot,omitempty"` - NicType string `json:"nicType,omitempty"` - Tags []string `json:"tags"` - Videoram Videoram `json:"videoram,omitempty"` - Vga string `json:"vga,omitempty"` - StartDelay int `json:startDelay,omitempty"` - Host string `json:"$container"` - - // These fields are used for passing in disk inputs when - // creating Vms, however, this is not a real field as far - // as the XO api or XAPI is concerned - Disks []Disk `json:"-"` - CloudNetworkConfig string `json:"-"` - VIFsMap []map[string]string `json:"-"` - WaitForIps bool `json:"-"` - Installation Installation `json:"-"` -} - -type Installation struct { - Method string `json:"-"` - Repository string `json:"-"` -} - -func (v Vm) Compare(obj interface{}) bool { - other := obj.(Vm) - if v.Id != "" && v.Id == other.Id { - return true - } - - if v.NameLabel != "" && v.NameLabel == other.NameLabel { - return true - } - if v.PowerState != "" && v.Host != "" { - if (v.PowerState == other.PowerState) && (v.Host == other.Host) { - return true - } - return false - } else if v.PowerState != "" && v.PowerState == other.PowerState { - return true - } else if v.Host != "" && v.Host == other.Host { - return true - } - if v.PoolId != "" && v.PoolId == other.PoolId { - return true - } - tagCount := len(v.Tags) - if tagCount > 0 { - for _, tag := range v.Tags { - if stringInSlice(tag, other.Tags) { - tagCount-- - } - } - - if tagCount == 0 { - return true - } - } - - return false -} - -func (c *Client) CreateVm(vmReq Vm, createTime time.Duration) (*Vm, error) { - tmpl, err := c.GetTemplate(Template{ - Id: vmReq.Template, - }) - - if err != nil { - return nil, err - } - - if len(tmpl) != 1 { - return nil, errors.New(fmt.Sprintf("cannot create VM when multiple templates are returned: %v", tmpl)) - } - - useExistingDisks := tmpl[0].isDiskTemplate() - installation := vmReq.Installation - if !useExistingDisks && installation.Method != "cdrom" && installation.Method != "network" { - return nil, errors.New("cannot create a VM from a diskless template without an ISO") - } - - existingDisks := map[string]interface{}{} - vdis := []interface{}{} - disks := vmReq.Disks - - firstDisk := createVdiMap(disks[0]) - // Treat the first disk differently. This covers the - // case where we are using a template with an already - // installed OS or a diskless template. - if useExistingDisks { - existingDisks["0"] = firstDisk - } else { - vdis = append(vdis, firstDisk) - } - - for i := 1; i < len(disks); i++ { - vdis = append(vdis, createVdiMap(disks[i])) - } - - params := map[string]interface{}{ - "affinityHost": vmReq.AffinityHost, - "bootAfterCreate": true, - "name_label": vmReq.NameLabel, - "name_description": vmReq.NameDescription, - "hvmBootFirmware": vmReq.Boot.Firmware, - "template": vmReq.Template, - "coreOs": false, - "cpuCap": nil, - "cpuWeight": nil, - "CPUs": vmReq.CPUs.Number, - "memoryMax": vmReq.Memory.Static[1], - "existingDisks": existingDisks, - "nicType": vmReq.NicType, - // TODO: (#145) Uncomment this once issues with secure_boot have been figured out - // "secureBoot": vmReq.SecureBoot, - "expNestedHvm": vmReq.ExpNestedHvm, - "VDIs": vdis, - "VIFs": vmReq.VIFsMap, - "tags": vmReq.Tags, - } - - videoram := vmReq.Videoram.Value - if videoram != 0 { - params["videoram"] = videoram - } - - vga := vmReq.Vga - if vga != "" { - params["vga"] = vga - } - - startDelay := vmReq.StartDelay - if startDelay != 0 { - params["startDelay"] = startDelay - } - - if len(vmReq.BlockedOperations) > 0 { - blockedOperations := map[string]string{} - for _, v := range vmReq.BlockedOperations { - blockedOperations[v] = "true" - } - params["blockedOperations"] = blockedOperations - } - - if installation.Method != "" { - params["installation"] = map[string]string{ - "method": installation.Method, - "repository": installation.Repository, - } - } - - cloudConfig := vmReq.CloudConfig - if cloudConfig != "" { - params["cloudConfig"] = cloudConfig - } - - resourceSet := vmReq.ResourceSet - if resourceSet != "" { - params["resourceSet"] = resourceSet - } - - cloudNetworkConfig := vmReq.CloudNetworkConfig - if cloudNetworkConfig != "" { - params["networkConfig"] = cloudNetworkConfig - } - log.Printf("[DEBUG] VM params for vm.create %#v", params) - var vmId string - err = c.Call("vm.create", params, &vmId) - - if err != nil { - return nil, err - } - - err = c.waitForModifyVm(vmId, vmReq.WaitForIps, createTime) - - if err != nil { - return nil, err - } - - return c.GetVm( - Vm{ - Id: vmId, - }, - ) -} - -func createVdiMap(disk Disk) map[string]interface{} { - return map[string]interface{}{ - "$SR": disk.SrId, - "SR": disk.SrId, - "name_label": disk.NameLabel, - "name_description": disk.NameDescription, - "size": disk.Size, - "type": "user", - } -} - -func (c *Client) UpdateVm(vmReq Vm) (*Vm, error) { - var resourceSet interface{} = vmReq.ResourceSet - if vmReq.ResourceSet == "" { - resourceSet = nil - } - params := map[string]interface{}{ - "id": vmReq.Id, - "affinityHost": vmReq.AffinityHost, - "name_label": vmReq.NameLabel, - "name_description": vmReq.NameDescription, - "hvmBootFirmware": vmReq.Boot.Firmware, - "auto_poweron": vmReq.AutoPoweron, - "resourceSet": resourceSet, - "high_availability": vmReq.HA, // valid options are best-effort, restart, '' - "CPUs": vmReq.CPUs.Number, - "memoryMax": vmReq.Memory.Static[1], - "nicType": vmReq.NicType, - "expNestedHvm": vmReq.ExpNestedHvm, - "startDelay": vmReq.StartDelay, - "vga": vmReq.Vga, - "videoram": vmReq.Videoram.Value, - // TODO: These need more investigation before they are implemented - // pv_args - - // virtualizationMode hvm or pv, cannot be set after vm is created (requires conversion) - - // hasVendorDevice must be applied when the vm is halted and only applies to windows machines - https://github.com/xapi-project/xen-api/blob/889b83c47d46c4df65fe58b01caed284dab8dc93/ocaml/idl/datamodel_vm.ml#L1168 - - // share relates to resource sets. This can be accomplished with the resource set resource so supporting it isn't necessary - - // cpusMask, cpuWeight and cpuCap can be changed at runtime to an integer value or null - // coresPerSocket is null or a number of cores per socket. Putting an invalid value doesn't seem to cause an error :( - } - - // TODO: (#145) Uncomment this once issues with secure_boot have been figured out - // secureBoot := vmReq.SecureBoot - // if secureBoot { - // params["secureBoot"] = true - // } - - blockedOperations := map[string]interface{}{} - for k, v := range vmReq.BlockedOperations { - if v == "false" { - blockedOperations[k] = nil - - } else { - blockedOperations[k] = v - } - } - params["blockedOperations"] = blockedOperations - - log.Printf("[DEBUG] VM params for vm.set: %#v", params) - - var success bool - err := c.Call("vm.set", params, &success) - - if err != nil { - return nil, err - } - - // TODO: This is a poor way to ensure that terraform will see the updated - // attributes after calling vm.set. Need to investigate a better way to detect this. - time.Sleep(25 * time.Second) - - return c.GetVm(vmReq) -} - -func (c *Client) StartVm(id string) error { - params := map[string]interface{}{ - "id": id, - } - var success bool - // TODO: This can block indefinitely before we get to the waitForVmHalt - err := c.Call("vm.start", params, &success) - - if err != nil { - return err - } - return c.waitForVmState( - id, - StateChangeConf{ - Pending: []string{"Halted", "Stopped"}, - Target: []string{"Running"}, - Timeout: 2 * time.Minute, - }, - ) -} - -func (c *Client) HaltVm(vmReq Vm) error { - params := map[string]interface{}{ - "id": vmReq.Id, - } - var success bool - // TODO: This can block indefinitely before we get to the waitForVmHalt - err := c.Call("vm.stop", params, &success) - - if err != nil { - return err - } - return c.waitForVmState( - vmReq.Id, - StateChangeConf{ - Pending: []string{"Running", "Stopped"}, - Target: []string{"Halted"}, - Timeout: 2 * time.Minute, - }, - ) -} - -func (c *Client) DeleteVm(id string) error { - params := map[string]interface{}{ - "id": id, - } - var reply []interface{} - return c.Call("vm.delete", params, &reply) -} - -func (c *Client) GetVm(vmReq Vm) (*Vm, error) { - obj, err := c.FindFromGetAllObjects(vmReq) - - if err != nil { - return nil, err - } - vms := obj.([]Vm) - - if len(vms) != 1 { - return nil, errors.New(fmt.Sprintf("expected to find a single VM from request %+v, instead found %d", vmReq, len(vms))) - } - - log.Printf("[DEBUG] Found vm: %+v", vms[0]) - return &vms[0], nil -} - -func (c *Client) GetVms(vm Vm) ([]Vm, error) { - obj, err := c.FindFromGetAllObjects(vm) - if err != nil { - return []Vm{}, err - } - vms := obj.([]Vm) - log.Printf("[DEBUG] Found vms: %+v", vms) - return vms, nil -} - -func (c *Client) EjectVmCd(vm *Vm) error { - params := map[string]interface{}{ - "id": vm.Id, - } - var result bool - err := c.Call("vm.ejectCd", params, &result) - if err != nil || !result { - return err - } - return nil -} - -func GetVmPowerState(c *Client, id string) func() (result interface{}, state string, err error) { - return func() (interface{}, string, error) { - vm, err := c.GetVm(Vm{Id: id}) - - if err != nil { - return vm, "", err - } - - return vm, vm.PowerState, nil - } -} - -func (c *Client) waitForVmState(id string, stateConf StateChangeConf) error { - stateConf.Refresh = GetVmPowerState(c, id) - _, err := stateConf.WaitForState() - return err -} - -func (c *Client) waitForModifyVm(id string, waitForIp bool, timeout time.Duration) error { - if !waitForIp { - refreshFn := func() (result interface{}, state string, err error) { - vm, err := c.GetVm(Vm{Id: id}) - - if err != nil { - return vm, "", err - } - - return vm, vm.PowerState, nil - } - stateConf := &StateChangeConf{ - Pending: []string{"Halted", "Stopped"}, - Refresh: refreshFn, - Target: []string{"Running"}, - Timeout: timeout, - } - _, err := stateConf.WaitForState() - return err - } else { - refreshFn := func() (result interface{}, state string, err error) { - vm, err := c.GetVm(Vm{Id: id}) - - if err != nil { - return vm, "", err - } - - l := len(vm.Addresses) - if l == 0 || vm.PowerState != "Running" { - return vm, "Waiting", nil - } - - return vm, "Ready", nil - } - stateConf := &StateChangeConf{ - Pending: []string{"Waiting"}, - Refresh: refreshFn, - Target: []string{"Ready"}, - Timeout: timeout, - } - _, err := stateConf.WaitForState() - return err - } -} - -func FindOrCreateVmForTests(vm *Vm, poolId, srId, templateName, tag string) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - fmt.Printf("failed to create client with error: %v\n", err) - os.Exit(-1) - } - - var vmRes *Vm - var net *Network - vmRes, err = c.GetVm(Vm{ - Tags: []string{tag}, - }) - - if _, ok := err.(NotFound); ok { - net, err = c.GetNetwork(Network{ - // We assume that a eth0 pool wide network exists - // since trying to discern what the appropriate network - // is from our current set of test inputs is challenging. - // If this proves problematic then it can be reconsidered. - NameLabel: "Pool-wide network associated with eth0", - PoolId: poolId, - }) - - if err != nil { - fmt.Println("Failed to get network to create a Vm for the tests") - os.Exit(-1) - } - - vmRes, err = c.CreateVm( - Vm{ - NameLabel: fmt.Sprintf("Terraform testing - %d", time.Now().Unix()), - Tags: []string{tag}, - Template: templateName, - CPUs: CPUs{ - Number: 1, - }, - Memory: MemoryObject{ - Static: []int{ - 0, 2147483648, - }, - }, - VIFsMap: []map[string]string{ - { - "network": net.Id, - }, - }, - Disks: []Disk{ - Disk{ - VDI: VDI{ - SrId: srId, - NameLabel: "terraform xenorchestra client testing", - Size: 16106127360, - }, - }, - Disk{ - VDI: VDI{ - SrId: srId, - NameLabel: "disk2", - Size: 16106127360, - }, - }, - }, - }, - 5*time.Minute, - ) - } - - if err != nil { - fmt.Println(fmt.Sprintf("failed to find vm for the client tests with error: %v\n", err)) - os.Exit(-1) - } - - *vm = *vmRes -} diff --git a/client/vm_test.go b/client/vm_test.go deleted file mode 100644 index 5340c412..00000000 --- a/client/vm_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package client - -import ( - "encoding/json" - "testing" -) - -var vmObjectData string = ` -{ - "type": "VM", - "addresses": {}, - "auto_poweron": false, - "boot": { - "order": "ncd" - }, - "CPUs": { - "max": 1, - "number": 1 - }, - "current_operations": {}, - "expNestedHvm": false, - "high_availability": "", - "memory": { - "dynamic": [ - 1073741824, - 1073741824 - ], - "static": [ - 536870912, - 1073741824 - ], - "size": 1073733632 - }, - "installTime": 1552287083, - "resourceSet": "U8kmJKszJC0", - "name_description": "Testingsdfsdf", - "name_label": "Hello from terraform!", - "other": { - "xo:resource_set": "\"U8kmJKszJC0\"", - "base_template_name": "Ubuntu Bionic Beaver 18.04", - "import_task": "OpaqueRef:a1c9c64b-eeec-48cd-b587-51a8fc7924d0", - "mac_seed": "bc583da8-d7a4-9437-7630-ce5ecce7efd0", - "install-methods": "cdrom,nfs,http,ftp", - "linux_template": "true" - }, - "os_version": {}, - "power_state": "Running", - "hasVendorDevice": false, - "snapshots": [], - "startTime": 1552445802, - "tags": [], - "VIFs": [ - "13793e84-110e-7f0d-8544-cb2f39adf2f4" - ], - "virtualizationMode": "hvm", - "xenTools": false, - "$container": "a5c7d15c-2724-47ce-8e30-77f21f08bb4c", - "$VBDs": [ - "43202d8a-c2ba-963e-54d0-b8cf770b2725", - "5b8adb53-36a7-8489-3a5f-f4ec8aa79568", - "5a12a8dd-f217-9f90-5aab-8f434893a6e3", - "567d6474-62ac-2d98-66ed-53cf468fc8b3", - "42eeb5e0-b14e-99c0-36a6-61b671112353" - ], - "VGPUs": [], - "$VGPUs": [], - "vga": "cirrus", - "videoram": "8", - "id": "77c6637c-fa3d-0a46-717e-296208c40169", - "uuid": "77c6637c-fa3d-0a46-717e-296208c40169", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" -}` - -var vmObjectWithNumericVideoram string = ` -{ - "videoram": 8 -}` - -var data string = ` -{ - "6944cce9-5ce0-a853-ee9c-bcc8281b597f": { - "body": "VM 'Test VM' started on host: xenserver-ddelnano (uuid: a5c7d15c-2724-47ce-8e30-77f21f08bb4c)", - "name": "VM_STARTED", - "time": 1547577637, - "$object": "5f318ba2-2300-cc34-3710-f64f53634ac0", - "id": "6944cce9-5ce0-a853-ee9c-bcc8281b597f", - "type": "message", - "uuid": "6944cce9-5ce0-a853-ee9c-bcc8281b597f", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" - }, - "52e21132-2f4f-3b80-ef65-7d43750eb6db": { - "body": "VM 'XOA' started on host: xenserver-ddelnano (uuid: a5c7d15c-2724-47ce-8e30-77f21f08bb4c)", - "name": "VM_STARTED", - "time": 1547578119, - "$object": "9df00260-c6d8-6cd4-4b24-d9e23602bf95", - "id": "52e21132-2f4f-3b80-ef65-7d43750eb6db", - "type": "message", - "uuid": "52e21132-2f4f-3b80-ef65-7d43750eb6db", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" - }, - "3bdc3bed-2a91-12af-5154-097706009593": { - "body": "VM 'XOA' started on host: xenserver-ddelnano (uuid: a5c7d15c-2724-47ce-8e30-77f21f08bb4c)", - "name": "VM_STARTED", - "time": 1547578434, - "$object": "2e793135-3b3d-354e-46c4-ef99fe0a37d0", - "id": "3bdc3bed-2a91-12af-5154-097706009593", - "type": "message", - "uuid": "3bdc3bed-2a91-12af-5154-097706009593", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" - }, - "ad97f23d-3bf0-7fac-e70c-ab98661450c6": { - "body": "VM 'XOA' shutdown forcibly", - "name": "VM_SHUTDOWN", - "time": 1547578721, - "$object": "9df00260-c6d8-6cd4-4b24-d9e23602bf95", - "id": "ad97f23d-3bf0-7fac-e70c-ab98661450c6", - "type": "message", - "uuid": "ad97f23d-3bf0-7fac-e70c-ab98661450c6", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" - }, - "77c6637c-fa3d-0a46-717e-296208c40169": { - "body": "VM 'XOA' shutdown forcibly", - "name": "VM_SHUTDOWN", - "time": 1547578721, - "$object": "9df00260-c6d8-6cd4-4b24-d9e23602bf95", - "id": "77c6637c-fa3d-0a46-717e-296208c40169", - "type": "VM", - "uuid": "ad97f23d-3bf0-7fac-e70c-ab98661450c6", - "$pool": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78", - "$poolId": "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" - } -} -` - -func TestUnmarshal(t *testing.T) { - var allObjectRes allObjectResponse - err := json.Unmarshal([]byte(data), &allObjectRes.Objects) - - if err != nil || allObjectRes.Objects["77c6637c-fa3d-0a46-717e-296208c40169"].Id != "77c6637c-fa3d-0a46-717e-296208c40169" { - t.Fatalf("error: %v. Need to have VM object: %v", err, allObjectRes) - } -} - -func TestUnmarshalingVmObject(t *testing.T) { - var vmObj Vm - - err := json.Unmarshal([]byte(vmObjectData), &vmObj) - - if err != nil { - t.Fatalf("error: %v. Need to have VM object: %v", err, vmObj) - } - - if !validateVmObject(vmObj) { - t.Fatalf("VmObject has not passed validation") - } - - var vmObjVideoramNumeric Vm - err = json.Unmarshal([]byte(vmObjectWithNumericVideoram), &vmObjVideoramNumeric) - - if err != nil { - t.Fatalf("error: %v. Need to have VM object: %v", err, vmObjVideoramNumeric) - } - - if vmObjVideoramNumeric.Videoram.Value != 8 { - t.Fatalf("Expected vm to Unmarshal from numerical videoram value") - } - -} - -func TestUpdateVmWithUpdatesThatRequireHalt(t *testing.T) { - c, err := NewClient(GetConfigFromEnv()) - if err != nil { - t.Fatalf("failed to create client with error: %v", err) - } - - prevCPUs := accVm.CPUs.Number - updatedCPUs := prevCPUs + 1 - vm, err := c.UpdateVm(Vm{Id: accVm.Id, CPUs: CPUs{Number: updatedCPUs}, NameLabel: "terraform testing", Memory: MemoryObject{Static: []int{0, 4294967296}}}) - - if err != nil { - t.Fatalf("failed to update vm with error: %v", err) - } - - if vm.CPUs.Number != updatedCPUs { - t.Errorf("failed to update VM cpus to %d", updatedCPUs) - } -} - -func validateVmObject(o Vm) bool { - if o.Type != "VM" { - return false - } - - if o.CPUs.Number != 1 { - return false - } - - if o.Memory.Size != 1073733632 { - return false - } - - if o.PowerState != "Running" { - return false - } - if o.VirtualizationMode != "hvm" { - return false - } - - if o.VIFs[0] != "13793e84-110e-7f0d-8544-cb2f39adf2f4" { - return false - } - - if o.PoolId != "cadf25ab-91ff-6fc0-041f-5a7033c4bc78" { - return false - } - - if o.ResourceSet == "" { - return false - } - - if o.Videoram.Value != 8 { - return false - } - - return true -} From 91914e8377ece2abc4c50898cec19bba8dfd4bbc Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 17 Nov 2021 19:24:10 +0100 Subject: [PATCH 2/3] Use the extracted XO SDK at github.com/vatesfr/xo-sdk-go Signed-off-by: Ringo De Smet --- go.mod | 4 ++-- go.sum | 2 ++ xoa/acc_setup_test.go | 2 +- xoa/data_source_cloud_config.go | 2 +- xoa/data_source_cloud_config_test.go | 2 +- xoa/data_source_host.go | 2 +- xoa/data_source_hosts.go | 2 +- xoa/data_source_pool.go | 2 +- xoa/data_source_resource_set.go | 2 +- xoa/data_source_resource_set_test.go | 2 +- xoa/data_source_user.go | 2 +- xoa/data_source_user_test.go | 2 +- xoa/data_source_vms.go | 2 +- xoa/data_source_xenorchestra_network.go | 2 +- xoa/data_source_xenorchestra_network_test.go | 2 +- xoa/data_source_xenorchestra_pif.go | 2 +- xoa/data_source_xenorchestra_sr.go | 2 +- xoa/data_source_xenorchestra_template.go | 2 +- xoa/data_source_xenorchestra_vdi.go | 2 +- xoa/internal/mocks.go | 2 +- xoa/provider.go | 2 +- xoa/resource_xenorchestra_acl.go | 2 +- xoa/resource_xenorchestra_acl_test.go | 2 +- xoa/resource_xenorchestra_cloud_config.go | 2 +- xoa/resource_xenorchestra_cloud_config_test.go | 2 +- xoa/resource_xenorchestra_resource_set.go | 2 +- xoa/resource_xenorchestra_resource_set_test.go | 2 +- xoa/resource_xenorchestra_vm.go | 2 +- xoa/resource_xenorchestra_vm_test.go | 2 +- 29 files changed, 31 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index c3b927d0..905b82b1 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/ddelnano/terraform-provider-xenorchestra go 1.16 require ( - github.com/ddelnano/terraform-provider-xenorchestra/client v0.0.0-00010101000000-000000000000 github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.3 + github.com/vatesfr/xo-sdk-go v0.0.0-20211117083644-f5fff1f340a0 ) -replace github.com/ddelnano/terraform-provider-xenorchestra/client => ./client +replace github.com/vatesfr/xo-sdk-go => ../xo-sdk-go diff --git a/go.sum b/go.sum index ac91a7d0..de354fe6 100644 --- a/go.sum +++ b/go.sum @@ -272,6 +272,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/vatesfr/xo-sdk-go v0.0.0-20211117083644-f5fff1f340a0 h1:KB9HIHDeWIvWSNkg0R8KtxiOOeZqKSvFZsqQmco0sAY= +github.com/vatesfr/xo-sdk-go v0.0.0-20211117083644-f5fff1f340a0/go.mod h1:IrDhel8mbGSApKL2n2W9JMj1aM5BFb4XNBlqbVtfycg= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= diff --git a/xoa/acc_setup_test.go b/xoa/acc_setup_test.go index c99f39e9..affb587c 100644 --- a/xoa/acc_setup_test.go +++ b/xoa/acc_setup_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" + "github.com/vatesfr/xo-sdk-go/client" ) var testObjectIndex int = 1 diff --git a/xoa/data_source_cloud_config.go b/xoa/data_source_cloud_config.go index 042719ba..f1ea9f36 100644 --- a/xoa/data_source_cloud_config.go +++ b/xoa/data_source_cloud_config.go @@ -5,8 +5,8 @@ import ( "fmt" "log" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaCloudConfig() *schema.Resource { diff --git a/xoa/data_source_cloud_config_test.go b/xoa/data_source_cloud_config_test.go index 85c79039..4477be1c 100644 --- a/xoa/data_source_cloud_config_test.go +++ b/xoa/data_source_cloud_config_test.go @@ -6,9 +6,9 @@ import ( "regexp" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) func TestAccXenorchestraDataSource_cloudConfig(t *testing.T) { diff --git a/xoa/data_source_host.go b/xoa/data_source_host.go index a4844689..2e6a53c6 100644 --- a/xoa/data_source_host.go +++ b/xoa/data_source_host.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaHost() *schema.Resource { diff --git a/xoa/data_source_hosts.go b/xoa/data_source_hosts.go index f228017c..6ff40f62 100644 --- a/xoa/data_source_hosts.go +++ b/xoa/data_source_hosts.go @@ -3,8 +3,8 @@ package xoa import ( "log" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaHosts() *schema.Resource { diff --git a/xoa/data_source_pool.go b/xoa/data_source_pool.go index c963790c..e03a57c8 100644 --- a/xoa/data_source_pool.go +++ b/xoa/data_source_pool.go @@ -5,8 +5,8 @@ import ( "fmt" "log" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaPool() *schema.Resource { diff --git a/xoa/data_source_resource_set.go b/xoa/data_source_resource_set.go index a486f92a..cb83dfa7 100644 --- a/xoa/data_source_resource_set.go +++ b/xoa/data_source_resource_set.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaResourceSet() *schema.Resource { diff --git a/xoa/data_source_resource_set_test.go b/xoa/data_source_resource_set_test.go index 0b6b724b..5c8628f8 100644 --- a/xoa/data_source_resource_set_test.go +++ b/xoa/data_source_resource_set_test.go @@ -5,9 +5,9 @@ import ( "regexp" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) var testResourceSetName string = "terraform-acc-data-source-test" diff --git a/xoa/data_source_user.go b/xoa/data_source_user.go index 09283b92..7864577c 100644 --- a/xoa/data_source_user.go +++ b/xoa/data_source_user.go @@ -3,8 +3,8 @@ package xoa import ( "log" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaUser() *schema.Resource { diff --git a/xoa/data_source_user_test.go b/xoa/data_source_user_test.go index 81b28524..4793d53f 100644 --- a/xoa/data_source_user_test.go +++ b/xoa/data_source_user_test.go @@ -6,9 +6,9 @@ import ( "regexp" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) func TestAccXenorchestraDataSource_user(t *testing.T) { diff --git a/xoa/data_source_vms.go b/xoa/data_source_vms.go index b6925339..f26139eb 100644 --- a/xoa/data_source_vms.go +++ b/xoa/data_source_vms.go @@ -4,9 +4,9 @@ import ( "log" "strings" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/ddelnano/terraform-provider-xenorchestra/xoa/internal" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaVms() *schema.Resource { diff --git a/xoa/data_source_xenorchestra_network.go b/xoa/data_source_xenorchestra_network.go index 401fba8c..47e35043 100644 --- a/xoa/data_source_xenorchestra_network.go +++ b/xoa/data_source_xenorchestra_network.go @@ -1,8 +1,8 @@ package xoa import ( - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaNetwork() *schema.Resource { diff --git a/xoa/data_source_xenorchestra_network_test.go b/xoa/data_source_xenorchestra_network_test.go index 376c7fb0..387829a0 100644 --- a/xoa/data_source_xenorchestra_network_test.go +++ b/xoa/data_source_xenorchestra_network_test.go @@ -5,9 +5,9 @@ import ( "regexp" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) var createNetwork = func(net client.Network, t *testing.T, times int) func() { diff --git a/xoa/data_source_xenorchestra_pif.go b/xoa/data_source_xenorchestra_pif.go index 8188d750..e2041631 100644 --- a/xoa/data_source_xenorchestra_pif.go +++ b/xoa/data_source_xenorchestra_pif.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaPIF() *schema.Resource { diff --git a/xoa/data_source_xenorchestra_sr.go b/xoa/data_source_xenorchestra_sr.go index 4479c45b..3e083633 100644 --- a/xoa/data_source_xenorchestra_sr.go +++ b/xoa/data_source_xenorchestra_sr.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaStorageRepository() *schema.Resource { diff --git a/xoa/data_source_xenorchestra_template.go b/xoa/data_source_xenorchestra_template.go index a901f688..99b7700f 100644 --- a/xoa/data_source_xenorchestra_template.go +++ b/xoa/data_source_xenorchestra_template.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaTemplate() *schema.Resource { diff --git a/xoa/data_source_xenorchestra_vdi.go b/xoa/data_source_xenorchestra_vdi.go index f6010bf7..5d806411 100644 --- a/xoa/data_source_xenorchestra_vdi.go +++ b/xoa/data_source_xenorchestra_vdi.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func dataSourceXoaVDI() *schema.Resource { diff --git a/xoa/internal/mocks.go b/xoa/internal/mocks.go index 7d880faf..74767db4 100644 --- a/xoa/internal/mocks.go +++ b/xoa/internal/mocks.go @@ -3,8 +3,8 @@ package internal import ( "errors" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) // failToStartAndHaltVmXOClient is a mock client used to ensure that HaltVm diff --git a/xoa/provider.go b/xoa/provider.go index 1b0fe510..aefb8d53 100644 --- a/xoa/provider.go +++ b/xoa/provider.go @@ -1,8 +1,8 @@ package xoa import ( - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func Provider() *schema.Provider { diff --git a/xoa/resource_xenorchestra_acl.go b/xoa/resource_xenorchestra_acl.go index 606340a8..11e6f645 100644 --- a/xoa/resource_xenorchestra_acl.go +++ b/xoa/resource_xenorchestra_acl.go @@ -1,9 +1,9 @@ package xoa import ( - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vatesfr/xo-sdk-go/client" ) var validActionOptions = []string{ diff --git a/xoa/resource_xenorchestra_acl_test.go b/xoa/resource_xenorchestra_acl_test.go index 44933d00..29b67b18 100644 --- a/xoa/resource_xenorchestra_acl_test.go +++ b/xoa/resource_xenorchestra_acl_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) func TestAccXenorchestraAcl_readAfterDelete(t *testing.T) { diff --git a/xoa/resource_xenorchestra_cloud_config.go b/xoa/resource_xenorchestra_cloud_config.go index 69e2e616..5532ac39 100644 --- a/xoa/resource_xenorchestra_cloud_config.go +++ b/xoa/resource_xenorchestra_cloud_config.go @@ -1,8 +1,8 @@ package xoa import ( - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vatesfr/xo-sdk-go/client" ) func resourceCloudConfigRecord() *schema.Resource { diff --git a/xoa/resource_xenorchestra_cloud_config_test.go b/xoa/resource_xenorchestra_cloud_config_test.go index db170c76..1d8eed1b 100644 --- a/xoa/resource_xenorchestra_cloud_config_test.go +++ b/xoa/resource_xenorchestra_cloud_config_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) func TestAccXenorchestraCloudConfig_readAfterDelete(t *testing.T) { diff --git a/xoa/resource_xenorchestra_resource_set.go b/xoa/resource_xenorchestra_resource_set.go index 716ec971..6edf5280 100644 --- a/xoa/resource_xenorchestra_resource_set.go +++ b/xoa/resource_xenorchestra_resource_set.go @@ -3,9 +3,9 @@ package xoa import ( "log" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vatesfr/xo-sdk-go/client" ) var validLimitType []string = []string{"cpus", "disk", "memory"} diff --git a/xoa/resource_xenorchestra_resource_set_test.go b/xoa/resource_xenorchestra_resource_set_test.go index e7cac820..9cfab671 100644 --- a/xoa/resource_xenorchestra_resource_set_test.go +++ b/xoa/resource_xenorchestra_resource_set_test.go @@ -4,10 +4,10 @@ import ( "fmt" "testing" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/ddelnano/terraform-provider-xenorchestra/xoa/internal" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) var rsName string = "terraform-acc-resource-set-resource" diff --git a/xoa/resource_xenorchestra_vm.go b/xoa/resource_xenorchestra_vm.go index 5c737396..007ebbe2 100644 --- a/xoa/resource_xenorchestra_vm.go +++ b/xoa/resource_xenorchestra_vm.go @@ -10,10 +10,10 @@ import ( "strconv" "time" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/ddelnano/terraform-provider-xenorchestra/xoa/internal" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vatesfr/xo-sdk-go/client" ) var validVga = []string{ diff --git a/xoa/resource_xenorchestra_vm_test.go b/xoa/resource_xenorchestra_vm_test.go index 1923150e..3728a51b 100644 --- a/xoa/resource_xenorchestra_vm_test.go +++ b/xoa/resource_xenorchestra_vm_test.go @@ -8,10 +8,10 @@ import ( "testing" "time" - "github.com/ddelnano/terraform-provider-xenorchestra/client" "github.com/ddelnano/terraform-provider-xenorchestra/xoa/internal" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/vatesfr/xo-sdk-go/client" ) func Test_extractIpsFromNetworks(t *testing.T) { From d39b2c588245ad86e790279470d5f405a0d02a95 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 17 Nov 2021 19:54:43 +0100 Subject: [PATCH 3/3] Comment out the replacement for local development Signed-off-by: Ringo De Smet --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 905b82b1..ec622047 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( github.com/vatesfr/xo-sdk-go v0.0.0-20211117083644-f5fff1f340a0 ) -replace github.com/vatesfr/xo-sdk-go => ../xo-sdk-go +// replace github.com/vatesfr/xo-sdk-go => ../xo-sdk-go