End of day backup commit

rc-1.0
Sergey Shubin svs1370 4 years ago
parent 132ed6d65e
commit 871a5e06ee

@ -63,8 +63,8 @@ type ControllerCfg struct {
app_id string // required for oauth2 mode
app_secret string // required for oauth2 mode
oauth2_url string // always required
decort_username string // assigned to either legacy_user (legacy mode) or Oauth2 user (oauth2 mode) upon successful verification
cc_client *http.Client // assigned when all initial check successfully passed
decort_username string // assigned to either legacy_user (legacy mode) or Oauth2 user (oauth2 mode) upon successful verification
cc_client *http.Client // assigned when all initial checks successfully passed
}
func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {

@ -1,5 +1,5 @@
/*
Copyright (c) 2019-2020 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
@ -39,24 +39,23 @@ import (
func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceRsgroupExists(...) method
log.Printf("%s", rg_facts)
log.Printf("flattenResgroup: ready to decode response body from %q", CloudspacesGetAPI)
details := CloudspacesGetResp{}
log.Debugf("%s", rg_facts)
log.Debugf("flattenResgroup: ready to decode response body from %q", CloudspacesGetAPI)
details := ResgroupGetResp{}
err := json.Unmarshal([]byte(rg_facts), &details)
if err != nil {
return err
}
log.Printf("flattenResgroup: decoded ResGroup name %q / ID %d, tenant ID %d, public IP %q",
details.Name, details.ID, details.TenantID, details.PublicIP)
log.Debugf("flattenResgroup: decoded ResGroup name %q / ID %d, account ID %d, public IP %q",
details.Name, details.ID, details.AccountID, details.PublicIP)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("name", details.Name)
d.Set("tenant_id", details.TenantID)
d.Set("account_id", details.AccountID)
d.Set("grid_id", details.GridID)
d.Set("public_ip", details.PublicIP) // legacy field - this may be obsoleted when new network segments are implemented
log.Printf("flattenResgroup: calling flattenQuota()")
log.Debugf("flattenResgroup: calling flattenQuota()")
if err = d.Set("quotas", flattenQuota(details.Quotas)); err != nil {
return err
}
@ -69,7 +68,7 @@ func dataSourceResgroupRead(d *schema.ResourceData, m interface{}) error {
if rg_facts == "" {
// if empty string is returned from utilityResgroupCheckPresence then there is no
// such resource group and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
d.SetId("") // ensure ID is empty in this case
return err
}
@ -95,13 +94,13 @@ func dataSourceResgroup() *schema.Resource {
Description: "Name of this resource group. Names are case sensitive and unique within the context of a tenant.",
},
"tenant": &schema.Schema {
"account": &schema.Schema {
Type: schema.TypeString,
Required: true,
Description: "Name of the tenant, which this resource group belongs to.",
},
"tenant_id": &schema.Schema {
"account_id": &schema.Schema {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the tenant, which this resource group belongs to.",
@ -113,12 +112,6 @@ func dataSourceResgroup() *schema.Resource {
Description: "Unique ID of the grid, where this resource group is deployed.",
},
"location": {
Type: schema.TypeString,
Computed: true,
Description: "Location of this resource group.",
},
"public_ip": { // this may be obsoleted as new network segments and true resource groups are implemented
Type: schema.TypeString,
Computed: true,

@ -60,8 +60,8 @@ type AccountAclRecord struct {
type ResgroupRecord struct {
ACLs []UserAclRecord `json:"ACLs"`
Owner AccountAclRecord `json:"accountAcl"`
TenantID int `json:"accountId"`
TenantName string `json:"accountName"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
@ -85,23 +85,6 @@ type ResgroupListResp []ResgroupRecord
// structures related to /cloudapi/rg/create API call
//
const ResgroupCreateAPI= "/restmachine/cloudapi/rg/create"
type ResgroupCreateParam struct {
TenantID int `json:"accountId"`
GridId int `json:"gid"`
Name string `json:"name"`
Ram int `json:"maxMemoryCapacity"`
Disk int `json:"maxVDiskCapacity"`
Cpu int `json:"maxCPUCapacity"`
NetTraffic int `json:"maxNetworkPeerTransfer"`
ExtIPs int `json:"maxNumPublicIP"`
Owner string `json:"owner"`
DefNet string `json:"def_net"`
IPCidr string `json:"ipcidr"`
Desc string `json:"decs"`
Reason string `json:"reason"`
ExtNetID int `json:"extNetId"`
ExtIP string `json:"extIp"`
}
//
// structures related to /cloudapi/rg/update API call
@ -139,8 +122,8 @@ const ResgroupGetAPI= "/restmachine/cloudapi/rg/get"
type ResgroupGetResp struct {
ACLs []UserAclRecord `json:"ACLs"`
Usage UsageRecord `json:"Resources"`
TenantID int `json:"accountId"`
TenantName string `json:"accountName"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
@ -182,11 +165,6 @@ type ResgroupUpdateParam struct {
// structures related to /cloudapi/rg/delete API
//
const ResgroupDeleteAPI = "/restmachine/cloudapi/rg/delete"
type ResgroupDeleteParam struct {
ID uint `json:"rgId"`
Force bool `json:"force"`
Reason string `json:"reason"`
}
//
// structures related to /cloudapi/kvmXXX/create APIs
@ -245,8 +223,8 @@ type SnapSetRecord struct {
}
type ComputeRecord struct {
TenantID int `json:"accountId"`
TenantName string `json:"accountName"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
ACLs []UserAclRecord `json:"acl"`
Arch string `json:"arch"`
BootDiskSize int `json:"bootdiskSize"`
@ -302,7 +280,7 @@ type SnapshotRecord struct {
type DiskRecord struct {
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
// was - Acl map[string]string `json:"acl"`
TenantID int `json:"accountId"`
AccountID int `json:"accountId"`
BootPartition int `json:"bootPartition"`
CreatedTime uint64 `json:"creationTime"`
DeletedTime uint64 `json:"deletionTime"`
@ -347,8 +325,8 @@ type ComputeGetParam struct {
}
type ComputeGetResp struct {
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
TenantID int `json:"accountId"`
TenantName string `json:"accountName"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
Arch string `json:"arch"`
BootDiskSize int `json:"bootdiskSize"`
CloneReference int `json:"cloneReference"`
@ -391,7 +369,7 @@ type ComputeGetResp struct {
// structures related to /restmachine/cloudapi/images/list API
//
type ImageRecord struct {
TenantID uint `json:"accountId"`
AccountID uint `json:"accountId"`
Arch string `json:"architecture`
BootType string `json:"bootType"`
IsBootable boo `json:"bootable"`
@ -411,7 +389,7 @@ type ImageRecord struct {
const ImagesListAPI = "/restmachine/cloudapi/images/list"
type ImagesListParam struct {
TenantID int `json:"accountId"`
AccountID int `json:"accountId"`
}
type ImagesListResp []ImageRecord
@ -426,7 +404,7 @@ type ExtNetRecord struct {
const ExtNetListAPI = "/restmachine/cloudapi/extnet/list"
type ExtNetListParam struct {
TenantID int `json:"accountId"`
AccountID int `json:"accountId"`
}
type ExtNetListResp []ExtNetRecord
@ -434,7 +412,7 @@ type ExtNetListResp []ExtNetRecord
//
// structures related to /cloudapi/accounts/list API
//
type TenantRecord struct {
type AccountRecord struct {
ACLs []UserAclRecord `json:"acl"`
CreatedTime uint64 `json:"creationTime"`
DeletedTime uint64 `json:"deletionTime"`
@ -444,8 +422,8 @@ type TenantRecord struct {
UpdatedTime uint64 `json:"updateTime"`
}
const TenantsListAPI = "/restmachine/cloudapi/accounts/list"
type TenantsListResp []TenantRecord
const AccountsListAPI = "/restmachine/cloudapi/accounts/list"
type AccountsListResp []AccountRecord
//
// structures related to /cloudapi/portforwarding/list API
@ -516,7 +494,7 @@ const ComputeDiskDetachAPI = "/restmachine/cloudapi/compute/diskDetach"
// structures related to /cloudapi/disks/create
//
type DiskCreateParam struct {
TenantID int `json:"accountId`
AccountID int `json:"accountId`
GridID int `json:"gid"`
Name string `json:"string"`
Description string `json:"description"`

@ -1,5 +1,5 @@
/*
Copyright (c) 2019-2020 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
@ -24,6 +24,8 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort
/*
type DiskConfig struct {
Label string
Size int
@ -65,7 +67,7 @@ type ComputeConfig struct {
Description string
// The following two parameters are required to create data disks by
// a separate disks/create API call
TenantID int
AccountID int
GridID int
// The following one paratmeter is required to create port forwards
// it will be obsoleted when we implement true Resource Groups
@ -81,8 +83,8 @@ type ResgroupQuotaConfig struct {
}
type ResgroupConfig struct {
TenantID int
TenantName string
AccountID int
AccountName string
Location string
Name string
ID int
@ -90,4 +92,6 @@ type ResgroupConfig struct {
ExtIP string // legacy field for VDC - this will eventually become obsoleted by true Resource Groups
Quota ResgroupQuotaConfig
Network NetworkConfig
}
}
*/

@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package decs
package decort
import (
@ -100,14 +100,18 @@ func Provider() *schema.Provider {
},
ResourcesMap: map[string]*schema.Resource {
"decs_resgroup": resourceResgroup(),
"decs_vm": resourceVm(),
"decort_resgroup": resourceResgroup(),
"decort_kvmx86": resourceKvmX86(),
"decort_disk": resourceDisk(),
"decort_vins": resourceVins(),
},
DataSourcesMap: map[string]*schema.Resource {
"decs_resgroup": dataSourceResgroup(),
"decs_vm": dataSourceVm(),
"decs_image": dataSourceImage(),
"decort_resgroup": dataSourceResgroup(),
"decs_kvmx86": dataSourceCompute(),
"decort_image": dataSourceImage(),
"decort_disk": dataSourceDisk(),
"decort_vins": dataSourceVins(),
},
ConfigureFunc: providerConfigure,

@ -35,12 +35,12 @@ import (
)
func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
log.Printf("resourceResgroupCreate: called for res group name %q, tenant name %q",
d.Get("name").(string), d.Get("tenant").(string))
log.Debugf("resourceResgroupCreate: called for res group name %q, account name %q",
d.Get("name").(string), d.Get("account").(string))
rg := &ResgroupConfig{
Name: d.Get("name").(string),
TenantName: d.Get("tenant").(string),
AccountName: d.Get("account").(string),
}
// validate that we have all parameters required to create the new Resource Group
@ -49,35 +49,55 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
if arg_set {
rg.Location = arg_value.(string)
} else {
return fmt.Errorf("Cannot create new resource group %q for tenant %q: missing location parameter.",
rg.Name, rg.TenantName)
return fmt.Errorf("Cannot create new RG %q for account %q: missing location parameter.",
rg.Name, rg.AccountName)
}
// tenant ID is required to create new resource group
// obtain Tenant ID by tenant name - it should not be zero on success
tenant_id, err := utilityGetTenantIdByName(rg.TenantName, m)
// account ID is required to create new resource group
// obtain Account ID by account name - it should not be zero on success
account_id, err := utilityGetAccountIdByName(rg.AccountName, m)
if err != nil {
return err
}
rg.TenantID = tenant_id
rg.AccountID = account_id
set_quotas := false
arg_value, arg_set = d.GetOk("quotas")
if arg_set {
log.Printf("resourceResgroupCreate: calling makeQuotaConfig")
log.Debugf("resourceResgroupCreate: calling makeQuotaConfig")
rg.Quota, _ = makeQuotaConfig(arg_value.([]interface{}))
set_quotas = true
}
controller := m.(*ControllerCfg)
log.Printf("resourceResgroupCreate: called by user %q for Resource group name %q, for tenant %q / ID %d, location %q",
log.Debugf("resourceResgroupCreate: called by user %q for RG name %q, for account %q / ID %d, location %q",
controller.getdecortUsername(),
rg.Name, d.Get("tenant"), rg.TenantID, rg.Location)
rg.Name, d.Get("account").(string), rg.AccountID, rg.Location)
/*
type ResgroupCreateParam struct {
AccountID int `json:"accountId"`
GridId int `json:"gid"`
Name string `json:"name"`
Ram int `json:"maxMemoryCapacity"`
Disk int `json:"maxVDiskCapacity"`
Cpu int `json:"maxCPUCapacity"`
NetTraffic int `json:"maxNetworkPeerTransfer"`
ExtIPs int `json:"maxNumPublicIP"`
Owner string `json:"owner"`
DefNet string `json:"def_net"`
IPCidr string `json:"ipcidr"`
Desc string `json:"decs"`
Reason string `json:"reason"`
ExtNetID int `json:"extNetId"`
ExtIP string `json:"extIp"`
}
*/
url_values := &url.Values{}
url_values.Add("accountId", fmt.Sprintf("%d", rg.TenantID))
url_values.Add("accountId", fmt.Sprintf("%d", rg.AccountID))
url_values.Add("name", rg.Name)
url_values.Add("location", rg.Location)
url_values.Add("access", controller.getdecortUsername())
url_values.Add("gid", rg.Location)
url_values.Add("owner", controller.getdecortUsername())
url_values.Add("def_net", "NONE")
// pass quota values as set
if set_quotas {
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", rg.Quota.Cpu))
@ -89,7 +109,7 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
// pass externalnetworkid if set
arg_value, arg_set = d.GetOk("extnet_id")
if arg_set {
url_values.Add("externalnetworkid", fmt.Sprintf("%d", arg_value))
url_values.Add("extNetId", fmt.Sprintf("%d", arg_value))
}
api_resp, err := controller.decortAPICall("POST", ResgroupCreateAPI, url_values)
@ -97,15 +117,15 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
return err
}
d.SetId(api_resp) // cloudspaces/create API plainly returns ID of the newly creted resource group on success
d.SetId(api_resp) // rg/create API returns ID of the newly creted resource group on success
rg.ID, _ = strconv.Atoi(api_resp)
return resourceResgroupRead(d, m)
}
func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
log.Printf("resourceResgroupRead: called for res group name %q, tenant name %q",
d.Get("name").(string), d.Get("tenant").(string))
log.Debugf("resourceResgroupRead: called for RG name %q, account name %q",
d.Get("name").(string), d.Get("account").(string))
rg_facts, err := utilityResgroupCheckPresence(d, m)
if rg_facts == "" {
// if empty string is returned from utilityResgroupCheckPresence then there is no
@ -119,13 +139,13 @@ func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
func resourceResgroupUpdate(d *schema.ResourceData, m interface{}) error {
// this method will only update quotas, if any are set
log.Printf("resourceResgroupUpdate: called for res group name %q, tenant name %q",
d.Get("name").(string), d.Get("tenant").(string))
log.Debugf("resourceResgroupUpdate: called for RG name %q, account name %q",
d.Get("name").(string), d.Get("account").(string))
quota_value, arg_set := d.GetOk("quotas")
if !arg_set {
// if there are no quotas set explicitly in the resource configuration - no change will be done
log.Printf("resourceResgroupUpdate: quotas are not set in the resource config - no update on this resource will be done")
log.Debugf("resourceResgroupUpdate: quotas are not set in the resource config - no update on this resource will be done")
return resourceResgroupRead(d, m)
}
quotaconfig_new, _ := makeQuotaConfig(quota_value.([]interface{}))
@ -142,66 +162,68 @@ func resourceResgroupUpdate(d *schema.ResourceData, m interface{}) error {
if quotaconfig_new.Cpu != quotaconfig_old.Cpu {
do_update = true
log.Printf("resourceResgroupUpdate: Cpu diff %d <- %d", quotaconfig_new.Cpu, quotaconfig_old.Cpu)
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotaconfig_new.Cpu, quotaconfig_old.Cpu)
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotaconfig_new.Cpu))
}
if quotaconfig_new.Disk != quotaconfig_old.Disk {
do_update = true
log.Printf("resourceResgroupUpdate: Disk diff %d <- %d", quotaconfig_new.Disk, quotaconfig_old.Disk)
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotaconfig_new.Disk, quotaconfig_old.Disk)
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotaconfig_new.Disk))
}
if quotaconfig_new.Ram != quotaconfig_old.Ram {
do_update = true
log.Printf("resourceResgroupUpdate: Ram diff %f <- %f", quotaconfig_new.Ram, quotaconfig_old.Ram)
log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotaconfig_new.Ram, quotaconfig_old.Ram)
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotaconfig_new.Ram))
}
if quotaconfig_new.NetTraffic != quotaconfig_old.NetTraffic {
do_update = true
log.Printf("resourceResgroupUpdate: NetTraffic diff %d <- %d", quotaconfig_new.NetTraffic, quotaconfig_old.NetTraffic)
log.Debugf("resourceResgroupUpdate: NetTraffic diff %d <- %d", quotaconfig_new.NetTraffic, quotaconfig_old.NetTraffic)
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quotaconfig_new.NetTraffic))
}
if quotaconfig_new.ExtIPs != quotaconfig_old.ExtIPs {
do_update = true
log.Printf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotaconfig_new.ExtIPs, quotaconfig_old.ExtIPs)
log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotaconfig_new.ExtIPs, quotaconfig_old.ExtIPs)
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quotaconfig_new.ExtIPs))
}
if do_update {
log.Printf("resourceResgroupUpdate: some new quotas are set - updating the resource")
log.Debugf("resourceResgroupUpdate: some new quotas are set - updating the resource")
_, err := controller.decortAPICall("POST", ResgroupUpdateAPI, url_values)
if err != nil {
return err
}
} else {
log.Printf("resourceResgroupUpdate: no difference in quotas between old and new state - no update on this resource will be done")
log.Debugf("resourceResgroupUpdate: no difference in quotas between old and new state - no update on this resource will be done")
}
return resourceResgroupRead(d, m)
}
func resourceResgroupDelete(d *schema.ResourceData, m interface{}) error {
// NOTE: this method destroys target resource group with flag "permanently", so there is no way to
// restore the destroyed resource group as well all VMs that existed in it
log.Printf("resourceResgroupDelete: called for res group name %q, tenant name %q",
d.Get("name").(string), d.Get("tenant").(string))
vm_facts, err := utilityResgroupCheckPresence(d, m)
if vm_facts == "" {
// the target VM does not exist - in this case according to Terraform best practice
// NOTE: this method forcibly destroys target resource group with flag "permanently", so there is no way to
// restore the destroyed resource group as well all Computes & VINSes that existed in it
log.Debugf("resourceResgroupDelete: called for RG name %q, account name %q",
d.Get("name").(string), d.Get("account").(string))
rg_facts, err := utilityResgroupCheckPresence(d, m)
if rg_facts == "" {
// the target RG does not exist - in this case according to Terraform best practice
// we exit from Destroy method without error
return nil
}
params := &url.Values{}
params.Add("cloudspaceId", d.Id())
params.Add("rgId", d.Id())
params.Add("force", "true")
params.Add("permanently", "true")
params.Add("reason", "Destroyed by DECORT Terraform provider")
controller := m.(*ControllerCfg)
vm_facts, err = controller.decortAPICall("POST", CloudspacesDeleteAPI, params)
vm_facts, err = controller.decortAPICall("POST", ResgroupDeleteAPI, params)
if err != nil {
return err
}
@ -243,13 +265,13 @@ func resourceResgroup() *schema.Resource {
"name": &schema.Schema {
Type: schema.TypeString,
Required: true,
Description: "Name of this resource group. Names are case sensitive and unique within the context of a tenant.",
Description: "Name of this resource group. Names are case sensitive and unique within the context of a account.",
},
"tenant": &schema.Schema {
"account": &schema.Schema {
Type: schema.TypeString,
Required: true,
Description: "Name of the tenant, which this resource group belongs to.",
Description: "Name of the account, which this resource group belongs to.",
},
"extnet_id": &schema.Schema {
@ -258,31 +280,18 @@ func resourceResgroup() *schema.Resource {
Description: "ID of the external network, which this resource group will be connected to by default.",
},
"tenant_id": &schema.Schema {
"account_id": &schema.Schema {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the tenant, which this resource group belongs to.",
Description: "Unique ID of the account, which this resource group belongs to.",
},
"grid_id": &schema.Schema {
Type: schema.TypeInt,
Computed: true,
Required: true,
Description: "Unique ID of the grid, where this resource group is deployed.",
},
"location": &schema.Schema {
Type: schema.TypeString,
Optional: true, // note that it is a REQUIRED parameter when creating new resource group
ForceNew: true,
Description: "Name of the location where this resource group should exist.",
},
"public_ip": { // this may be obsoleted as new network segments and true resource groups are implemented
Type: schema.TypeString,
Computed: true,
Description: "Public IP address of this resource group (if any).",
},
"quotas": {
Type: schema.TypeList,
Optional: true,

@ -1,5 +1,5 @@
/*
Copyright (c) 2019-2020 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
@ -36,23 +36,24 @@ import (
// "github.com/hashicorp/terraform/helper/validation"
)
func (ctrl *ControllerCfg) utilityResgroupConfigGet(rgid int) (*ResgroupConfig, error) {
func (ctrl *ControllerCfg) utilityResgroupConfigGet(rgid int) (*ResgroupGetResp, error) {
url_values := &url.Values{}
url_values.Add("cloudspaceId", fmt.Sprintf("%d", rgid))
resgroup_facts, err := ctrl.decortAPICall("POST", CloudspacesGetAPI, url_values)
url_values.Add("rgId", fmt.Sprintf("%d", rgid))
resgroup_facts, err := ctrl.decortAPICall("POST", ResgroupGetAPI, url_values)
if err != nil {
return nil, err
}
log.Printf("utilityResgroupConfigGet: ready to unmarshal string %q", resgroup_facts)
model := CloudspacesGetResp{}
err = json.Unmarshal([]byte(resgroup_facts), &model)
log.Debugf("utilityResgroupConfigGet: ready to unmarshal string %q", resgroup_facts)
model := &ResgroupGetResp{}
err = json.Unmarshal([]byte(resgroup_facts), model)
if err != nil {
return nil, err
}
/*
ret := &ResgroupConfig{}
ret.TenantID = model.TenantID
ret.AccountID = model.AccountID
ret.Location = model.Location
ret.Name = model.Name
ret.ID = rgid
@ -60,53 +61,58 @@ func (ctrl *ControllerCfg) utilityResgroupConfigGet(rgid int) (*ResgroupConfig,
ret.ExtIP = model.ExtIP // legacy field for VDC - this will eventually become obsoleted by true Resource Groups
// Quota ResgroupQuotaConfig
// Network NetworkConfig
log.Printf("utilityResgroupConfigGet: tenant ID %d, GridID %d, ExtIP %q",
model.TenantID, model.GridID, model.ExtIP)
*/
log.Debugf("utilityResgroupConfigGet: account ID %d, GridID %d, Name %s",
model.AccountID, model.GridID, model.Name)
return ret, nil
return model, nil
}
func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate resource group by its name and tenant name.
// This function tries to locate resource group by its name and account name.
// If succeeded, it returns non empty string that contains JSON formatted facts about the
// resource group as returned by cloudspaces/get API call.
// Otherwise it returns empty string and meaningful error.
//
// NOTE: As our provider always deletes RGs permanently, there is no "restore" method and
// consequently we are not interested in matching RGs in DELETED state. Hence, we call
// .../rg/list API with includedeleted=false
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for the resource's Exists method.
//
name := d.Get("name").(string)
tenant_name := d.Get("tenant").(string)
account_name := d.Get("account").(string)
controller := m.(*ControllerCfg)
url_values := &url.Values{}
url_values.Add("includedeleted", "false")
body_string, err := controller.decortAPICall("POST", CloudspacesListAPI, url_values)
body_string, err := controller.decortAPICall("POST", ResgroupListAPI, url_values)
if err != nil {
return "", err
}
log.Printf("%s", body_string)
log.Printf("utilityResgroupCheckPresence: ready to decode response body from %q", CloudspacesListAPI)
log.Debugf("%s", body_string)
log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %q", ResgroupListAPI)
model := CloudspacesListResp{}
err = json.Unmarshal([]byte(body_string), &model)
if err != nil {
return "", err
}
log.Printf("utilityResgroupCheckPresence: traversing decoded Json of length %d", len(model))
log.Debugf("utilityResgroupCheckPresence: traversing decoded Json of length %d", len(model))
for index, item := range model {
// need to match VDC by name & tenant name
if item.Name == name && item.TenantName == tenant_name {
log.Printf("utilityResgroupCheckPresence: match ResGroup name %q / ID %d, tenant %q at index %d",
item.Name, item.ID, item.TenantName, index)
// need to match RG by name & account name
if item.Name == name && item.AccountName == account_name {
log.Debugf("utilityResgroupCheckPresence: match RG name %q / ID %d, account %q at index %d",
item.Name, item.ID, item.AccountName, index)
// not all required information is returned by cloudspaces/list API, so we need to initiate one more
// call to cloudspaces/get to obtain extra data to complete Resource population.
// not all required information is returned by rg/list API, so we need to initiate one more
// call to rg/get to obtain extra data to complete Resource population.
// Namely, we need to extract resource quota settings
req_values := &url.Values{}
req_values.Add("cloudspaceId", fmt.Sprintf("%d", item.ID))
body_string, err := controller.decortAPICall("POST", CloudspacesGetAPI, req_values)
req_values.Add("rgId", fmt.Sprintf("%d", item.ID))
body_string, err := controller.decortAPICall("POST", ResgroupGetAPI, req_values)
if err != nil {
return "", err
}
@ -115,32 +121,32 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
}
}
return "", fmt.Errorf("Cannot find resource group name %q owned by tenant %q", name, tenant_name)
return "", fmt.Errorf("Cannot find RG name %q owned by account %q", name, account_name)
}
func utilityGetTenantIdByName(tenant_name string, m interface{}) (int, error) {
func utilityGetAccountIdByName(account_name string, m interface{}) (int, error) {
controller := m.(*ControllerCfg)
url_values := &url.Values{}
body_string, err := controller.decortAPICall("POST", TenantsListAPI, url_values)
body_string, err := controller.decortAPICall("POST", AccountsListAPI, url_values)
if err != nil {
return 0, err
}
model := TenantsListResp{}
model := AccountsListResp{}
err = json.Unmarshal([]byte(body_string), &model)
if err != nil {
return 0, err
}
log.Printf("utilityGetTenantIdByName: traversing decoded Json of length %d", len(model))
log.Debugf("utilityGetAccountIdByName: traversing decoded Json of length %d", len(model))
for index, item := range model {
// need to match Tenant by name
if item.Name == tenant_name {
log.Printf("utilityGetTenantIdByName: match Tenant name %q / ID %d at index %d",
// need to match Account by name
if item.Name == account_name {
log.Debugf("utilityGetAccountIdByName: match Account name %q / ID %d at index %d",
item.Name, item.ID, index)
return item.ID, nil
}
}
return 0, fmt.Errorf("Cannot find tenant %q for the current user. Check tenant value and your access rights", tenant_name)
return 0, fmt.Errorf("Cannot find account %q for the current user. Check account value and your access rights", account_name)
}
Loading…
Cancel
Save