diff --git a/decort/data_source_account.go b/decort/data_source_account.go index 735384f..2db3008 100644 --- a/decort/data_source_account.go +++ b/decort/data_source_account.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (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 import ( - "encoding/json" - "fmt" - // "net/url" - - log "github.com/sirupsen/logrus" - + "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -func flattenAccount(d *schema.ResourceData, acc_facts string) error { - // NOTE: this function modifies ResourceData argument - as such it should never be called - // from resourceAccountExists(...) method - - // log.Debugf("flattenAccount: ready to decode response body from %q", CloudspacesGetAPI) - details := AccountRecord{} - err := json.Unmarshal([]byte(acc_facts), &details) +func dataSourceAccountRead(d *schema.ResourceData, m interface{}) error { + acc, err := utilityAccountCheckPresence(d, m) if err != nil { return err } - log.Debugf("flattenAccount: decoded Account name %q / ID %d, status %q", details.Name, details.ID, details.Status) - - d.SetId(fmt.Sprintf("%d", details.ID)) - d.Set("name", details.Name) - d.Set("status", details.Status) - + id := uuid.New() + d.SetId(id.String()) + d.Set("dc_location", acc.DCLocation) + d.Set("resources", flattenAccResources(acc.Resources)) + 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 } -func dataSourceAccountRead(d *schema.ResourceData, m interface{}) error { - acc_facts, err := utilityAccountCheckPresence(d, m) - if acc_facts == "" { - // if empty string is returned from utilityAccountCheckPresence then there is no - // such account and err tells so - just return it to the calling party - d.SetId("") // ensure ID is empty in this case - return err +func flattenAccResources(r Resources) []map[string]interface{} { + res := make([]map[string]interface{}, 0) + temp := map[string]interface{}{ + "current": flattenAccResource(r.Current), + "reserved": flattenAccResource(r.Reserved), } + res = append(res, temp) + return res +} + +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 +} - return flattenAccount(d, acc_facts) +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 { @@ -77,56 +330,6 @@ func dataSourceAccount() *schema.Resource { Default: &Timeout60s, }, - Schema: map[string]*schema.Schema{ - "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." - }, - */ - }, + Schema: dataSourceAccountSchemaMake(), } } diff --git a/decort/data_source_account_audits_list.go b/decort/data_source_account_audits_list.go index 3475527..c31e947 100644 --- a/decort/data_source_account_audits_list.go +++ b/decort/data_source_account_audits_list.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/decort/data_source_account_computes_list.go b/decort/data_source_account_computes_list.go index b4b99ad..8a7ba77 100644 --- a/decort/data_source_account_computes_list.go +++ b/decort/data_source_account_computes_list.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/decort/data_source_account_disks_list.go b/decort/data_source_account_disks_list.go index 6c33ced..def9676 100644 --- a/decort/data_source_account_disks_list.go +++ b/decort/data_source_account_disks_list.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/decort/data_source_account_list.go b/decort/data_source_account_list.go index c6f6919..866f232 100644 --- a/decort/data_source_account_list.go +++ b/decort/data_source_account_list.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/decort/data_source_account_vins_list.go b/decort/data_source_account_vins_list.go index 27307ff..e9d50e7 100644 --- a/decort/data_source_account_vins_list.go +++ b/decort/data_source_account_vins_list.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/decort/models_api.go b/decort/models_api.go index d783626..3c07f8b 100644 --- a/decort/models_api.go +++ b/decort/models_api.go @@ -1002,7 +1002,9 @@ const accountDeleteAccountsAPI = "/cloudapi/account/deleteAccounts" const accountDeleteUserAPI = "/cloudapi/account/deleteUser" const accountDisableAPI = "/cloudapi/account/disable" 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 accountGetConsumedCloudUnitsByTypeAPI = "/cloudapi/account/getConsumedCloudUnitsByType" const accountGetConsumptionGetAPI = "/cloudapi/account/getConsumption" diff --git a/decort/resource_rg.go b/decort/resource_rg.go index 4a07cb6..5528bb4 100644 --- a/decort/resource_rg.go +++ b/decort/resource_rg.go @@ -39,10 +39,6 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error { // Valid account ID is required to create new resource group // 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") 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 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 set_quota := false @@ -77,10 +73,10 @@ func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error { controller := m.(*ControllerCfg) log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d", controller.getDecortUsername(), - rg_name.(string), validated_account_id) + rg_name.(string), d.Get("account_id").(int)) 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("gid", fmt.Sprintf("%d", DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention url_values.Add("owner", controller.getDecortUsername()) diff --git a/decort/utility_account.go b/decort/utility_account.go index c9a6def..f2b5e2e 100644 --- a/decort/utility_account.go +++ b/decort/utility_account.go @@ -1,6 +1,6 @@ /* -Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. -Author: Sergey Shubin, , +Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Stanislav Solovev, , Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,131 +26,31 @@ package decort import ( "encoding/json" - "fmt" "net/url" + "strconv" log "github.com/sirupsen/logrus" "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) urlValues := &url.Values{} - accId, argSet := d.GetOk("account_id") - if argSet { - // get Account right away by its ID - log.Debugf("utilityAccountCheckPresence: locating Account by its ID %d", accId.(int)) - urlValues.Add("accountId", fmt.Sprintf("%d", accId.(int))) - apiResp, err := controller.decortAPICall("POST", AccountsGetAPI, urlValues) - if err != nil { - return "", err - } - return apiResp, nil - } - - accName, argSet := d.GetOk("name") - 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 { - return "", 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)) - 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)) -} + urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int))) -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) + log.Debugf("utilityAccountCheckPresence: load account") + accountRaw, err := controller.decortAPICall("POST", accountGetAPI, urlValues) if err != nil { - return 0, err + return nil, err } - model := AccountsListResp{} - err = json.Unmarshal([]byte(apiResp), &model) + err = json.Unmarshal([]byte(accountRaw), &account) 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 nil, err } - return 0, fmt.Errorf("Cannot find account %q for the current user. Check account name and your access rights", accName.(string)) + return account, nil } diff --git a/decort/utility_disk.go b/decort/utility_disk.go index 1422c03..c9a8605 100644 --- a/decort/utility_disk.go +++ b/decort/utility_disk.go @@ -16,16 +16,15 @@ limitations under the License. */ /* -This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration +This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration Technology platfom. -Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates. +Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates. */ package decort import ( - "encoding/json" "fmt" "net/url" @@ -36,16 +35,15 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) - 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: // - if disk ID is specified -> by disk ID // - if disk name is specifeid -> by disk name and either account ID or account name // // NOTE: disk names are not unique, so the first occurence of this name in the account will // be returned. There is no such ambiguity when locating disk by its ID. - // + // // If succeeded, it returns non empty string that contains JSON formatted facts about the disk // as returned by disks/get API call. // Otherwise it returns empty string and meaningful error. @@ -64,7 +62,7 @@ func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, er if err != nil || theId <= 0 { diskId, argSet := d.GetOk("disk_id") if argSet { - theId =diskId.(int) + theId = diskId.(int) idSet = true } } else { @@ -92,18 +90,14 @@ func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, er // Valid account ID is required to locate disks // 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) if err != nil { return "", err } - log.Debugf("utilityDiskCheckPresence: ready to unmarshal string %s", diskFacts) + log.Debugf("utilityDiskCheckPresence: ready to unmarshal string %s", diskFacts) disksList := DisksListResp{} err = json.Unmarshal([]byte(diskFacts), &disksList) @@ -119,25 +113,25 @@ func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, er log.Debugf("utilityDiskCheckPresence: index %d, matched disk name %q", index, item.Name) // we found the disk we need - not get detailed information via API call to disks/get /* - // TODO: this may not be optimal as it initiates one extra call to the DECORT controller - // in spite of the fact that we already have all required information about the disk in - // item variable - // - get_urlValues := &url.Values{} - get_urlValues.Add("diskId", fmt.Sprintf("%d", item.ID)) - diskFacts, err = controller.decortAPICall("POST", DisksGetAPI, get_urlValues) - if err != nil { - return "", err - } - return diskFacts, nil + // TODO: this may not be optimal as it initiates one extra call to the DECORT controller + // in spite of the fact that we already have all required information about the disk in + // item variable + // + get_urlValues := &url.Values{} + get_urlValues.Add("diskId", fmt.Sprintf("%d", item.ID)) + diskFacts, err = controller.decortAPICall("POST", DisksGetAPI, get_urlValues) + if err != nil { + return "", err + } + return diskFacts, nil */ reencodedItem, err := json.Marshal(item) if err != nil { return "", err } - return string(reencodedItem[:]), nil + return string(reencodedItem[:]), nil } } return "", nil // there should be no error if disk does not exist -} \ No newline at end of file +} diff --git a/decort/utility_rg.go b/decort/utility_rg.go index 371e678..6a62ebd 100644 --- a/decort/utility_rg.go +++ b/decort/utility_rg.go @@ -104,7 +104,7 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string } else { idSet = true } - + if idSet { // go straight for the RG by its ID log.Debugf("utilityResgroupCheckPresence: locating RG by its ID %d", theId) @@ -124,10 +124,6 @@ func utilityResgroupCheckPresence(d *schema.ResourceData, m interface{}) (string // Valid account ID is required to locate a resource group // 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") 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)) for index, item := range model { // 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", 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) { @@ -172,4 +168,4 @@ func utilityResgroupGetDefaultGridID() (interface{}, error) { } return "", fmt.Errorf("utilityResgroupGetDefaultGridID: invalid default Grid ID %d", DefaultGridID) - } +} diff --git a/samples/README.md b/samples/README.md index 7a61d08..3b091f7 100644 --- a/samples/README.md +++ b/samples/README.md @@ -25,6 +25,7 @@ - account_disks_list - account_vins_list - account_audits_list + - account - resources: - image - virtual_image diff --git a/samples/data_account/main.tf b/samples/data_account/main.tf new file mode 100644 index 0000000..1cc63dc --- /dev/null +++ b/samples/data_account/main.tf @@ -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 = + controller_url = "https://ds1.digitalenergy.online" + #oauth2_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 +}