Add data function for an account
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -25,45 +25,298 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
|
|||||||
package decort
|
package decort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"github.com/google/uuid"
|
||||||
"fmt"
|
|
||||||
// "net/url"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func flattenAccount(d *schema.ResourceData, acc_facts string) error {
|
func dataSourceAccountRead(d *schema.ResourceData, m interface{}) error {
|
||||||
// NOTE: this function modifies ResourceData argument - as such it should never be called
|
acc, err := utilityAccountCheckPresence(d, m)
|
||||||
// from resourceAccountExists(...) method
|
|
||||||
|
|
||||||
// log.Debugf("flattenAccount: ready to decode response body from %q", CloudspacesGetAPI)
|
|
||||||
details := AccountRecord{}
|
|
||||||
err := json.Unmarshal([]byte(acc_facts), &details)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("flattenAccount: decoded Account name %q / ID %d, status %q", details.Name, details.ID, details.Status)
|
id := uuid.New()
|
||||||
|
d.SetId(id.String())
|
||||||
d.SetId(fmt.Sprintf("%d", details.ID))
|
d.Set("dc_location", acc.DCLocation)
|
||||||
d.Set("name", details.Name)
|
d.Set("resources", flattenAccResources(acc.Resources))
|
||||||
d.Set("status", details.Status)
|
d.Set("ckey", acc.CKey)
|
||||||
|
d.Set("meta", flattenMeta(acc.Meta))
|
||||||
|
d.Set("acl", flattenRgAcl(acc.Acl))
|
||||||
|
d.Set("company", acc.Company)
|
||||||
|
d.Set("companyurl", acc.CompanyUrl)
|
||||||
|
d.Set("created_by", acc.CreatedBy)
|
||||||
|
d.Set("created_time", acc.CreatedTime)
|
||||||
|
d.Set("deactivation_time", acc.DeactiovationTime)
|
||||||
|
d.Set("deleted_by", acc.DeletedBy)
|
||||||
|
d.Set("deleted_time", acc.DeletedTime)
|
||||||
|
d.Set("displayname", acc.DisplayName)
|
||||||
|
d.Set("guid", acc.GUID)
|
||||||
|
d.Set("account_id", acc.ID)
|
||||||
|
d.Set("account_name", acc.Name)
|
||||||
|
d.Set("resource_limits", flattenRgResourceLimits(acc.ResourceLimits))
|
||||||
|
d.Set("send_access_emails", acc.SendAccessEmails)
|
||||||
|
d.Set("service_account", acc.ServiceAccount)
|
||||||
|
d.Set("status", acc.Status)
|
||||||
|
d.Set("updated_time", acc.UpdatedTime)
|
||||||
|
d.Set("version", acc.Version)
|
||||||
|
d.Set("vins", acc.Vins)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dataSourceAccountRead(d *schema.ResourceData, m interface{}) error {
|
func flattenAccResources(r Resources) []map[string]interface{} {
|
||||||
acc_facts, err := utilityAccountCheckPresence(d, m)
|
res := make([]map[string]interface{}, 0)
|
||||||
if acc_facts == "" {
|
temp := map[string]interface{}{
|
||||||
// if empty string is returned from utilityAccountCheckPresence then there is no
|
"current": flattenAccResource(r.Current),
|
||||||
// such account and err tells so - just return it to the calling party
|
"reserved": flattenAccResource(r.Reserved),
|
||||||
d.SetId("") // ensure ID is empty in this case
|
}
|
||||||
return err
|
res = append(res, temp)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
return flattenAccount(d, acc_facts)
|
func flattenAccResource(r Resource) []map[string]interface{} {
|
||||||
|
res := make([]map[string]interface{}, 0)
|
||||||
|
temp := map[string]interface{}{
|
||||||
|
"cpu": r.CPU,
|
||||||
|
"disksize": r.Disksize,
|
||||||
|
"extips": r.Extips,
|
||||||
|
"exttraffic": r.Exttraffic,
|
||||||
|
"gpu": r.GPU,
|
||||||
|
"ram": r.RAM,
|
||||||
|
}
|
||||||
|
res = append(res, temp)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAccountSchemaMake() map[string]*schema.Schema {
|
||||||
|
res := map[string]*schema.Schema{
|
||||||
|
"account_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"dc_location": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"current": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cpu": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"disksize": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"extips": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"exttraffic": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"gpu": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"ram": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"reserved": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cpu": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"disksize": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"extips": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"exttraffic": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"gpu": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"ram": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ckey": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"acl": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"explicit": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"guid": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"user_group_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"companyurl": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"created_by": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"created_time": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"deactivation_time": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"deleted_by": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"deleted_time": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"displayname": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"guid": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"account_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"resource_limits": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cu_c": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"cu_d": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"cu_i": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"cu_m": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"cu_np": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"gpu_units": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"send_access_emails": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"service_account": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"updated_time": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"vins": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func dataSourceAccount() *schema.Resource {
|
func dataSourceAccount() *schema.Resource {
|
||||||
@@ -77,56 +330,6 @@ func dataSourceAccount() *schema.Resource {
|
|||||||
Default: &Timeout60s,
|
Default: &Timeout60s,
|
||||||
},
|
},
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: dataSourceAccountSchemaMake(),
|
||||||
"name": {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
Description: "Name of the account. Names are case sensitive and unique.",
|
|
||||||
},
|
|
||||||
|
|
||||||
"account_id": {
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
Description: "Unique ID of the account. If account ID is specified, then account name is ignored.",
|
|
||||||
},
|
|
||||||
|
|
||||||
"status": {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Computed: true,
|
|
||||||
Description: "Current status of the account.",
|
|
||||||
},
|
|
||||||
|
|
||||||
/* We keep the following attributes commented out, as we are not implementing account
|
|
||||||
management with Terraform plugin, so we do not need this extra info.
|
|
||||||
|
|
||||||
"quota": {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Optional: true,
|
|
||||||
MaxItems: 1,
|
|
||||||
Elem: &schema.Resource{
|
|
||||||
Schema: quotaRgSubresourceSchema(), // this is a dictionary
|
|
||||||
},
|
|
||||||
Description: "Quotas on the resources for this account and all its resource groups.",
|
|
||||||
},
|
|
||||||
|
|
||||||
"resource_groups": {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema {
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
},
|
|
||||||
Description: "IDs of resource groups in this account."
|
|
||||||
},
|
|
||||||
|
|
||||||
"vins": {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema {
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
},
|
|
||||||
Description: "IDs of VINSes created at the account level."
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -1002,7 +1002,9 @@ const accountDeleteAccountsAPI = "/cloudapi/account/deleteAccounts"
|
|||||||
const accountDeleteUserAPI = "/cloudapi/account/deleteUser"
|
const accountDeleteUserAPI = "/cloudapi/account/deleteUser"
|
||||||
const accountDisableAPI = "/cloudapi/account/disable"
|
const accountDisableAPI = "/cloudapi/account/disable"
|
||||||
const accountEnableAPI = "/cloudapi/account/enable"
|
const accountEnableAPI = "/cloudapi/account/enable"
|
||||||
const accountGetAPI = "/cloudapi/account/get"
|
|
||||||
|
//const accountGetAPI = "/restmachine/cloudapi/account/get"
|
||||||
|
const accountGetAPI = "/restmachine/cloudbroker/account/get"
|
||||||
const accountGetConsumedAccountUnitsAPI = "/cloudapi/account/getConsumedAccountUnits"
|
const accountGetConsumedAccountUnitsAPI = "/cloudapi/account/getConsumedAccountUnits"
|
||||||
const accountGetConsumedCloudUnitsByTypeAPI = "/cloudapi/account/getConsumedCloudUnitsByType"
|
const accountGetConsumedCloudUnitsByTypeAPI = "/cloudapi/account/getConsumedCloudUnitsByType"
|
||||||
const accountGetConsumptionGetAPI = "/cloudapi/account/getConsumption"
|
const accountGetConsumptionGetAPI = "/cloudapi/account/getConsumption"
|
||||||
|
|||||||
@@ -39,10 +39,6 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|||||||
|
|
||||||
// Valid account ID is required to create new resource group
|
// Valid account ID is required to create new resource group
|
||||||
// obtain Account ID by account name - it should not be zero on success
|
// obtain Account ID by account name - it should not be zero on success
|
||||||
validated_account_id, err := utilityGetAccountIdBySchema(d, m)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rg_name, arg_set := d.GetOk("name")
|
rg_name, arg_set := d.GetOk("name")
|
||||||
if !arg_set {
|
if !arg_set {
|
||||||
@@ -62,7 +58,7 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|||||||
|
|
||||||
// all required parameters are set in the schema - we can continue with RG creation
|
// all required parameters are set in the schema - we can continue with RG creation
|
||||||
log.Debugf("resourceResgroupCreate: called for RG name %s, account ID %d",
|
log.Debugf("resourceResgroupCreate: called for RG name %s, account ID %d",
|
||||||
rg_name.(string), validated_account_id)
|
rg_name.(string), d.Get("account_id").(int))
|
||||||
|
|
||||||
// quota settings are optional
|
// quota settings are optional
|
||||||
set_quota := false
|
set_quota := false
|
||||||
@@ -77,10 +73,10 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
|
|||||||
controller := m.(*ControllerCfg)
|
controller := m.(*ControllerCfg)
|
||||||
log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d",
|
log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d",
|
||||||
controller.getDecortUsername(),
|
controller.getDecortUsername(),
|
||||||
rg_name.(string), validated_account_id)
|
rg_name.(string), d.Get("account_id").(int))
|
||||||
|
|
||||||
url_values := &url.Values{}
|
url_values := &url.Values{}
|
||||||
url_values.Add("accountId", fmt.Sprintf("%d", validated_account_id))
|
url_values.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
|
||||||
url_values.Add("name", rg_name.(string))
|
url_values.Add("name", rg_name.(string))
|
||||||
url_values.Add("gid", fmt.Sprintf("%d", DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
|
url_values.Add("gid", fmt.Sprintf("%d", DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
|
||||||
url_values.Add("owner", controller.getDecortUsername())
|
url_values.Add("owner", controller.getDecortUsername())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
|
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -26,131 +26,31 @@ package decort
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||||
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func utilityAccountCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
|
func utilityAccountCheckPresence(d *schema.ResourceData, m interface{}) (*AccountWithResources, error) {
|
||||||
|
account := &AccountWithResources{}
|
||||||
controller := m.(*ControllerCfg)
|
controller := m.(*ControllerCfg)
|
||||||
urlValues := &url.Values{}
|
urlValues := &url.Values{}
|
||||||
|
|
||||||
accId, argSet := d.GetOk("account_id")
|
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
|
||||||
if argSet {
|
|
||||||
// get Account right away by its ID
|
log.Debugf("utilityAccountCheckPresence: load account")
|
||||||
log.Debugf("utilityAccountCheckPresence: locating Account by its ID %d", accId.(int))
|
accountRaw, err := controller.decortAPICall("POST", accountGetAPI, urlValues)
|
||||||
urlValues.Add("accountId", fmt.Sprintf("%d", accId.(int)))
|
|
||||||
apiResp, err := controller.decortAPICall("POST", AccountsGetAPI, urlValues)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
|
||||||
return apiResp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
accName, argSet := d.GetOk("name")
|
err = json.Unmarshal([]byte(accountRaw), &account)
|
||||||
if !argSet {
|
|
||||||
// neither ID nor name - no account for you!
|
|
||||||
return "", fmt.Errorf("Cannot check account presence if name is empty and no account ID specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
apiResp, err := controller.decortAPICall("POST", AccountsListAPI, urlValues)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
|
||||||
// log.Debugf("%s", apiResp)
|
|
||||||
// log.Debugf("utilityAccountCheckPresence: ready to decode response body from %q", AccountsListAPI)
|
|
||||||
accList := AccountsListResp{}
|
|
||||||
err = json.Unmarshal([]byte(apiResp), &accList)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("utilityAccountCheckPresence: traversing decoded Json of length %d", len(accList))
|
return account, nil
|
||||||
for index, item := range accList {
|
|
||||||
// match by account name
|
|
||||||
if item.Name == accName.(string) {
|
|
||||||
log.Debugf("utilityAccountCheckPresence: match account name %q / ID %d at index %d",
|
|
||||||
item.Name, item.ID, index)
|
|
||||||
|
|
||||||
// NB: unlike accounts/get API, accounts/list API returns abridged set of account info,
|
|
||||||
// for instance it does not return quotas
|
|
||||||
|
|
||||||
reencodedItem, err := json.Marshal(item)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(reencodedItem[:]), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("Cannot find account name %q", accName.(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
func utilityGetAccountIdBySchema(d *schema.ResourceData, m interface{}) (int, error) {
|
|
||||||
/*
|
|
||||||
This function expects schema that contains the following two elements:
|
|
||||||
|
|
||||||
"account_name": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: Optional,
|
|
||||||
Description: "Name of the account, ....",
|
|
||||||
},
|
|
||||||
|
|
||||||
"account_id": &schema.Schema{
|
|
||||||
Type: schema.TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
Description: "Unique ID of the account, ....",
|
|
||||||
},
|
|
||||||
|
|
||||||
Then it will check, which argument is set, and if account name is present, it will
|
|
||||||
initiate API calls to the DECORT cloud controller and try to match relevant account
|
|
||||||
by the name.
|
|
||||||
|
|
||||||
NOTE that for some resources (most notably, Resource Group) "account_name" attribute is
|
|
||||||
marked as "Computed: true", so the only way to fully identify Resource Group is to specify
|
|
||||||
"account_id", which is marked as "Required: true"
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
accId, argSet := d.GetOk("account_id")
|
|
||||||
if argSet {
|
|
||||||
if accId.(int) > 0 {
|
|
||||||
return accId.(int), nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("Account ID must be positive")
|
|
||||||
}
|
|
||||||
|
|
||||||
accName, argSet := d.GetOk("account_name")
|
|
||||||
if !argSet {
|
|
||||||
return 0, fmt.Errorf("Either non-empty account name or valid account ID must be specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
controller := m.(*ControllerCfg)
|
|
||||||
urlValues := &url.Values{}
|
|
||||||
apiResp, err := controller.decortAPICall("POST", AccountsListAPI, urlValues)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
model := AccountsListResp{}
|
|
||||||
err = json.Unmarshal([]byte(apiResp), &model)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("utilityGetAccountIdBySchema: traversing decoded Json of length %d", len(model))
|
|
||||||
for index, item := range model {
|
|
||||||
// need to match Account by name
|
|
||||||
if item.Name == accName.(string) {
|
|
||||||
log.Debugf("utilityGetAccountIdBySchema: match Account name %q / ID %d at index %d",
|
|
||||||
item.Name, item.ID, index)
|
|
||||||
return item.ID, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, fmt.Errorf("Cannot find account %q for the current user. Check account name and your access rights", accName.(string))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
|
|||||||
package decort
|
package decort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -36,7 +35,6 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
|
func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
|
||||||
// This function tries to locate Disk by one of the following algorithms depending on
|
// This function tries to locate Disk by one of the following algorithms depending on
|
||||||
// the parameters passed:
|
// the parameters passed:
|
||||||
@@ -92,12 +90,8 @@ func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, er
|
|||||||
|
|
||||||
// Valid account ID is required to locate disks
|
// Valid account ID is required to locate disks
|
||||||
// obtain Account ID by account name - it should not be zero on success
|
// obtain Account ID by account name - it should not be zero on success
|
||||||
validatedAccountId, err := utilityGetAccountIdBySchema(d, m)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
urlValues.Add("accountId", fmt.Sprintf("%d", validatedAccountId))
|
urlValues.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
|
||||||
diskFacts, err := controller.decortAPICall("POST", DisksListAPI, urlValues)
|
diskFacts, err := controller.decortAPICall("POST", DisksListAPI, urlValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -124,10 +124,6 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
|
|||||||
|
|
||||||
// Valid account ID is required to locate a resource group
|
// Valid account ID is required to locate a resource group
|
||||||
// obtain Account ID by account name - it should not be zero on success
|
// obtain Account ID by account name - it should not be zero on success
|
||||||
validatedAccountId, err := utilityGetAccountIdBySchema(d, m)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
urlValues.Add("includedeleted", "false")
|
urlValues.Add("includedeleted", "false")
|
||||||
apiResp, err := controller.decortAPICall("POST", ResgroupListAPI, urlValues)
|
apiResp, err := controller.decortAPICall("POST", ResgroupListAPI, urlValues)
|
||||||
@@ -145,7 +141,7 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
|
|||||||
log.Debugf("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 {
|
for index, item := range model {
|
||||||
// match by RG name & account ID
|
// match by RG name & account ID
|
||||||
if item.Name == rgName.(string) && item.AccountID == validatedAccountId {
|
if item.Name == rgName.(string) && item.AccountID == d.Get("account_id").(int) {
|
||||||
log.Debugf("utilityResgroupCheckPresence: match RG name %s / ID %d, account ID %d at index %d",
|
log.Debugf("utilityResgroupCheckPresence: match RG name %s / ID %d, account ID %d at index %d",
|
||||||
item.Name, item.ID, item.AccountID, index)
|
item.Name, item.ID, item.AccountID, index)
|
||||||
|
|
||||||
@@ -163,7 +159,7 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, validatedAccountId)
|
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, d.Get("account_id").(int))
|
||||||
}
|
}
|
||||||
|
|
||||||
func utilityResgroupGetDefaultGridID() (interface{}, error) {
|
func utilityResgroupGetDefaultGridID() (interface{}, error) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
- account_disks_list
|
- account_disks_list
|
||||||
- account_vins_list
|
- account_vins_list
|
||||||
- account_audits_list
|
- account_audits_list
|
||||||
|
- account
|
||||||
- resources:
|
- resources:
|
||||||
- image
|
- image
|
||||||
- virtual_image
|
- virtual_image
|
||||||
|
|||||||
39
samples/data_account/main.tf
Normal file
39
samples/data_account/main.tf
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Пример использования
|
||||||
|
Получение информации об аккаунте
|
||||||
|
|
||||||
|
*/
|
||||||
|
#Расскомментируйте этот код,
|
||||||
|
#и внесите необходимые правки в версию и путь,
|
||||||
|
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
|
||||||
|
/*
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
decort = {
|
||||||
|
version = "1.1"
|
||||||
|
source = "digitalenergy.online/decort/decort"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
provider "decort" {
|
||||||
|
authenticator = "oauth2"
|
||||||
|
#controller_url = <DECORT_CONTROLLER_URL>
|
||||||
|
controller_url = "https://ds1.digitalenergy.online"
|
||||||
|
#oauth2_url = <DECORT_SSO_URL>
|
||||||
|
oauth2_url = "https://sso.digitalenergy.online"
|
||||||
|
allow_unverified_ssl = true
|
||||||
|
}
|
||||||
|
|
||||||
|
data "decort_account" "a" {
|
||||||
|
#id аккаунта
|
||||||
|
#обязательный параметр
|
||||||
|
#тип - число
|
||||||
|
account_id = 28096
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
output "test" {
|
||||||
|
value = data.decort_account.a
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user