Compare commits

...

9 Commits

Author SHA1 Message Date
KasimBaybikov
f5e0a53364 3.4.3 2023-02-16 16:29:04 +03:00
stSolo
9d1c8eeaa7 3.4.2 2023-02-10 17:29:09 +03:00
stSolo
8516e0419a 3.4.1 2023-02-08 17:28:20 +03:00
stSolo
e12afbe1ad 3.4.0 2023-01-26 11:32:11 +03:00
stSolo
c0c9dc8131 fix changelog file 2023-01-25 18:12:01 +03:00
stSolo
c3bc6ef5da fix changelog file 2023-01-25 17:06:56 +03:00
stSolo
4d865ae921 3.4.0 2023-01-24 17:50:38 +03:00
KasimBaybikov
a355247845 v3.3.1 2022-12-26 18:08:23 +03:00
KasimBaybikov
be86069155 version 3.3.0 2022-12-20 18:05:17 +03:00
103 changed files with 5999 additions and 1237 deletions

View File

@@ -2,7 +2,7 @@ name: Release
on:
push:
tags:
- 'v*'
- '*'
jobs:
release:

View File

@@ -1,10 +1,11 @@
### Version 3.2.2
### Bug fixes
- Fix bug with getting kvmvm data_source
### Version 3.4.3
### Features
- Add enable/disable functionality for kvmvm resource
- Add status checker for kvmvm resource
- Change field type disksize from int to float in:
- resource decort_resgroup
- resource decort_account
- data source decort_rg
- data source decort_account
- data source decort_account_rg_list
- Models of the resources

View File

@@ -1,10 +0,0 @@
FROM docker.io/hashicorp/terraform:latest
WORKDIR /opt/decort/tf/
COPY provider.tf ./
COPY terraform-provider-decort ./terraform.d/plugins/digitalenergy.online/decort/decort/3.2.2/linux_amd64/
RUN terraform init
WORKDIR /tf
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh", "/bin/terraform"]

View File

@@ -1,52 +0,0 @@
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: alpine
image: alpine:3.15
command:
- sleep
- infinity
'''
}
}
stages {
stage('Dependency check') {
environment {
DEPCHECKDB = credentials('depcheck-postgres')
}
steps {
container('alpine') {
sh 'apk update && apk add openjdk11 java-postgresql-jdbc go'
dependencyCheck additionalArguments: '-f JSON -f HTML -n --enableExperimental \
-l deplog \
--dbDriverName org.postgresql.Driver \
--dbDriverPath /usr/share/java/postgresql-jdbc.jar \
--dbUser $DEPCHECKDB_USR \
--dbPassword $DEPCHECKDB_PSW \
--connectionString jdbc:postgresql://postgres-postgresql.postgres/depcheck', odcInstallation: 'depcheck'
sh 'cat deplog'
}
}
}
stage('SonarQube analysis') {
environment {
SONARSCANNER_HOME = tool 'sonarscanner'
}
steps {
withSonarQubeEnv('sonarqube') {
sh '$SONARSCANNER_HOME/bin/sonar-scanner'
}
}
}
stage('SonarQube quality gate') {
steps {
waitForQualityGate webhookSecretId: 'sonar-webhook', abortPipeline: true
}
}
}
}

View File

@@ -52,4 +52,4 @@ test:
echo $(TEST) | xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4
testacc:
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m

View File

@@ -2,12 +2,15 @@
Terraform provider для платформы Digital Energy Cloud Orchestration Technology (DECORT)
Внимание: провайдер версии 3.x разработан для DECORT API 3.8.x.
Для более старых версий можно использовать:
## Соответсвие версий платформы версиям провайдера
- DECORT API 3.7.x - версия провайдера rc-1.25
- DECORT API 3.6.x - версия провайдера rc-1.10
- DECORT API до 3.6.0 - terraform DECS provider (https://github.com/rudecs/terraform-provider-decs)
| Версия DECORT API | Версия провайдера Terraform |
| ------ | ------ |
| 3.8.5 | 3.4.x |
| 3.8.0 - 3.8.4 | 3.3.1 |
| 3.7.x | rc-1.25 |
| 3.6.x | rc-1.10 |
| до 3.6.0 | [terraform-provider-decs](https://github.com/rudecs/terraform-provider-decs) |
## Режимы работы

View File

@@ -2,11 +2,15 @@
Terraform provider for Digital Energy Cloud Orchestration Technology (DECORT) platform
NOTE: provider 3.x is designed for DECORT API 3.8.x. For older API versions please use:
## Mapping of platform versions with provider versions
- DECORT API 3.7.x versions - provider verion rc-1.25
- DECORT API 3.6.x versions - provider version rc-1.10
- DECORT API versions prior to 3.6.0 - Terraform DECS provider (https://github.com/rudecs/terraform-provider-decs)
| DECORT API version | Terraform provider version |
| ------ | ------ |
| 3.8.5 | 3.4.x |
| 3.8.0 - 3.8.4 | 3.3.1 |
| 3.7.x | rc-1.25 |
| 3.6.x | rc-1.10 |
| до 3.6.0 | [terraform-provider-decs](https://github.com/rudecs/terraform-provider-decs) |
## Working modes

View File

@@ -1,4 +0,0 @@
#!/bin/sh
cp -aL /opt/decort/tf/* /opt/decort/tf/.* ./
exec "$@"

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

53
internal/dc/warnings.go Normal file
View File

@@ -0,0 +1,53 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
//Diagnostics Collector
package dc
import "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
type Warnings struct {
diagnostics diag.Diagnostics
}
func (w *Warnings) Add(err error) {
if w.diagnostics == nil {
w.diagnostics = diag.Diagnostics{}
}
diagFromErr := diag.FromErr(err)
diagFromErr[0].Severity = diag.Warning
w.diagnostics = append(w.diagnostics, diagFromErr[0])
}
func (w Warnings) Get() diag.Diagnostics {
return w.diagnostics
}

View File

@@ -46,6 +46,12 @@ func NewDataSourcesMap() map[string]*schema.Resource {
"decort_k8s_wg": k8s.DataSourceK8sWg(),
"decort_k8s_wg_list": k8s.DataSourceK8sWgList(),
"decort_vins": vins.DataSourceVins(),
"decort_vins_list": vins.DataSourceVinsList(),
"decort_vins_audits": vins.DataSourceVinsAudits(),
"decort_vins_ip_list": vins.DataSourceVinsIpList(),
"decort_vins_list_deleted": vins.DataSourceVinsListDeleted(),
"decort_vins_ext_net_list": vins.DataSourceVinsExtNetList(),
"decort_vins_nat_rule_list": vins.DataSourceVinsNatRuleList(),
"decort_snapshot_list": snapshot.DataSourceSnapshotList(),
"decort_disk": disks.DataSourceDisk(),
"decort_disk_list": disks.DataSourceDiskList(),
@@ -77,7 +83,6 @@ func NewDataSourcesMap() map[string]*schema.Resource {
"decort_extnet_computes_list": extnet.DataSourceExtnetComputesList(),
"decort_extnet": extnet.DataSourceExtnet(),
"decort_extnet_default": extnet.DataSourceExtnetDefault(),
"decort_vins_list": vins.DataSourceVinsList(),
"decort_locations_list": locations.DataSourceLocationsList(),
"decort_location_url": locations.DataSourceLocationUrl(),
"decort_image_list": image.DataSourceImageList(),

View File

@@ -141,6 +141,22 @@ func flattenAccResources(r Resources) []map[string]interface{} {
return res
}
func flattenAccountSeps(seps map[string]map[string]ResourceSep) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for sepKey, sepVal := range seps {
for dataKey, dataVal := range sepVal {
temp := map[string]interface{}{
"sep_id": sepKey,
"data_name": dataKey,
"disk_size": dataVal.DiskSize,
"disk_size_max": dataVal.DiskSizeMax,
}
res = append(res, temp)
}
}
return res
}
func flattenAccResource(r Resource) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
@@ -150,6 +166,7 @@ func flattenAccResource(r Resource) []map[string]interface{} {
"exttraffic": r.Exttraffic,
"gpu": r.GPU,
"ram": r.RAM,
"seps": flattenAccountSeps(r.SEPs),
}
res = append(res, temp)
return res
@@ -161,6 +178,7 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Required: true,
},
"dc_location": {
Type: schema.TypeString,
Computed: true,
@@ -180,7 +198,7 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"disksize": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"extips": {
@@ -199,6 +217,30 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
@@ -212,7 +254,7 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"disksize": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"extips": {
@@ -231,6 +273,30 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},

View File

@@ -47,6 +47,7 @@ func flattenAccountDisksList(adl AccountDisksList) []map[string]interface{} {
"disk_name": ad.Name,
"pool": ad.Pool,
"sep_id": ad.SepId,
"shareable": ad.Shareable,
"size_max": ad.SizeMax,
"type": ad.Type,
}
@@ -98,6 +99,10 @@ func dataSourceAccountDisksListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"shareable": {
Type: schema.TypeBool,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -74,12 +74,41 @@ func flattenAccRGComputes(argc AccountRGComputes) []map[string]interface{} {
return res
}
func flattenAccResourceHack(r ResourceHack) []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,
//"seps": flattenAccountSeps(r.SEPs),
}
res = append(res, temp)
return res
}
func flattenAccResourceRg(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 flattenAccRGResources(argr AccountRGResources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"consumed": flattenAccResource(argr.Consumed),
"limits": flattenAccResource(argr.Limits),
"reserved": flattenAccResource(argr.Reserved),
"consumed": flattenAccResourceRg(argr.Consumed),
"limits": flattenAccResourceHack(argr.Limits),
"reserved": flattenAccResourceRg(argr.Reserved),
}
res = append(res, temp)
return res

View File

@@ -89,13 +89,19 @@ type AccountCloudApi struct {
type AccountCloudApiList []AccountCloudApi
type ResourceSep struct {
DiskSize float64 `json:"disksize"`
DiskSizeMax int `json:"disksizemax"`
}
type Resource struct {
CPU int `json:"cpu"`
Disksize int `json:"disksize"`
Extips int `json:"extips"`
Exttraffic int `json:"exttraffic"`
GPU int `json:"gpu"`
RAM int `json:"ram"`
CPU int `json:"cpu"`
Disksize float64 `json:"disksize"`
Extips int `json:"extips"`
Exttraffic int `json:"exttraffic"`
GPU int `json:"gpu"`
RAM int `json:"ram"`
SEPs map[string]map[string]ResourceSep `json:"seps"`
}
type Resources struct {
@@ -147,12 +153,13 @@ type AccountCompute struct {
type AccountComputesList []AccountCompute
type AccountDisk struct {
ID int `json:"id"`
Name string `json:"name"`
Pool string `json:"pool"`
SepId int `json:"sepId"`
SizeMax int `json:"sizeMax"`
Type string `json:"type"`
ID int `json:"id"`
Name string `json:"name"`
Pool string `json:"pool"`
SepId int `json:"sepId"`
Shareable bool `json:"shareable"`
SizeMax int `json:"sizeMax"`
Type string `json:"type"`
}
type AccountDisksList []AccountDisk
@@ -194,10 +201,19 @@ type AccountRGComputes struct {
Stopped int `json:"Stopped"`
}
type ResourceHack struct {
CPU int `json:"cpu"`
Disksize float64 `json:"disksize"`
Extips int `json:"extips"`
Exttraffic int `json:"exttraffic"`
GPU int `json:"gpu"`
RAM int `json:"ram"`
}
type AccountRGResources struct {
Consumed Resource `json:"Consumed"`
Limits Resource `json:"Limits"`
Reserved Resource `json:"Reserved"`
Consumed Resource `json:"Consumed"`
Limits ResourceHack `json:"Limits"`
Reserved Resource `json:"Reserved"`
}
type AccountRG struct {

View File

@@ -574,7 +574,7 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"disksize": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"extips": {
@@ -593,6 +593,30 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
@@ -606,7 +630,7 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"disksize": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"extips": {
@@ -625,6 +649,30 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},

View File

@@ -47,4 +47,6 @@ const (
disksSnapshotDeleteAPI = "/restmachine/cloudapi/disks/snapshotDelete"
disksSnapshotRollbackAPI = "/restmachine/cloudapi/disks/snapshotRollback"
disksShareAPI = "/restmachine/cloudapi/disks/share"
disksUnshareAPI = "/restmachine/cloudapi/disks/unshare"
)

View File

@@ -60,8 +60,7 @@ func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface
d.Set("account_name", disk.AccountName)
d.Set("acl", string(diskAcl))
d.Set("boot_partition", disk.BootPartition)
d.Set("compute_id", disk.ComputeID)
d.Set("compute_name", disk.ComputeName)
d.Set("computes", flattenDiskComputes(disk.Computes))
d.Set("created_time", disk.CreatedTime)
d.Set("deleted_time", disk.DeletedTime)
d.Set("desc", disk.Desc)
@@ -84,6 +83,7 @@ func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface
d.Set("passwd", disk.Passwd)
d.Set("pci_slot", disk.PciSlot)
d.Set("pool", disk.Pool)
d.Set("present_to", disk.PresentTo)
d.Set("purge_attempts", disk.PurgeAttempts)
d.Set("purge_time", disk.PurgeTime)
d.Set("reality_device_number", disk.RealityDeviceNumber)
@@ -93,6 +93,7 @@ func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface
d.Set("role", disk.Role)
d.Set("sep_id", disk.SepID)
d.Set("sep_type", disk.SepType)
d.Set("shareable", disk.Shareable)
d.Set("size_max", disk.SizeMax)
d.Set("size_used", disk.SizeUsed)
d.Set("snapshots", flattenDiskSnapshotList(disk.Snapshots))
@@ -130,15 +131,21 @@ func dataSourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Number of disk partitions",
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Compute ID",
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
Description: "Compute name",
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeString,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_time": {
Type: schema.TypeInt,
@@ -316,6 +323,13 @@ func dataSourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Pool for disk location",
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
@@ -361,13 +375,17 @@ func dataSourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Type SEP. Defines the type of storage system and contains one of the values set in the cloud platform",
},
"shareable": {
Type: schema.TypeBool,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Computed: true,
Description: "Size in GB",
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
Description: "Number of used space, in GB",
},

View File

@@ -42,6 +42,18 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func flattenDiskComputes(computes map[string]string) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for computeKey, computeVal := range computes {
temp := map[string]interface{}{
"compute_id": computeKey,
"compute_name": computeVal,
}
res = append(res, temp)
}
return res
}
func flattenIOTune(iot IOTune) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
@@ -72,9 +84,8 @@ func flattenDiskList(dl DisksList) []map[string]interface{} {
"account_id": disk.AccountID,
"account_name": disk.AccountName,
"acl": string(diskAcl),
"computes": flattenDiskComputes(disk.Computes),
"boot_partition": disk.BootPartition,
"compute_id": disk.ComputeID,
"compute_name": disk.ComputeName,
"created_time": disk.CreatedTime,
"deleted_time": disk.DeletedTime,
"desc": disk.Desc,
@@ -99,6 +110,7 @@ func flattenDiskList(dl DisksList) []map[string]interface{} {
"passwd": disk.Passwd,
"pci_slot": disk.PciSlot,
"pool": disk.Pool,
"present_to": disk.PresentTo,
"purge_attempts": disk.PurgeAttempts,
"purge_time": disk.PurgeTime,
"reality_device_number": disk.RealityDeviceNumber,
@@ -108,6 +120,7 @@ func flattenDiskList(dl DisksList) []map[string]interface{} {
"role": disk.Role,
"sep_id": disk.SepID,
"sep_type": disk.SepType,
"shareable": disk.Shareable,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"snapshots": flattenDiskSnapshotList(disk.Snapshots),
@@ -199,15 +212,21 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Number of disk partitions",
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Compute ID",
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
Description: "Compute name",
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeString,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_time": {
Type: schema.TypeInt,
@@ -400,6 +419,13 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Pool for disk location",
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
@@ -445,13 +471,17 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Type SEP. Defines the type of storage system and contains one of the values set in the cloud platform",
},
"shareable": {
Type: schema.TypeBool,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Computed: true,
Description: "Size in GB",
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
Description: "Number of used space, in GB",
},

View File

@@ -415,7 +415,7 @@ func dataSourceDiskListUnattachedSchemaMake() map[string]*schema.Schema {
Description: "Size in GB",
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
Description: "Number of used space, in GB",
},

View File

@@ -37,9 +37,8 @@ type Disk struct {
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
BootPartition int `json:"bootPartition"`
Computes map[string]string `json:"computes"`
CreatedTime uint64 `json:"creationTime"`
ComputeID int `json:"computeId"`
ComputeName string `json:"computeName"`
DeletedTime uint64 `json:"deletionTime"`
DeviceName string `json:"devicename"`
Desc string `json:"desc"`
@@ -63,6 +62,7 @@ type Disk struct {
ParentId int `json:"parentId"`
PciSlot int `json:"pciSlot"`
Pool string `json:"pool"`
PresentTo []int `json:"presentTo"`
PurgeTime uint64 `json:"purgeTime"`
PurgeAttempts uint64 `json:"purgeAttempts"`
RealityDeviceNumber int `json:"realityDeviceNumber"`
@@ -71,9 +71,10 @@ type Disk struct {
ResName string `json:"resName"`
Role string `json:"role"`
SepType string `json:"sepType"`
Shareable bool `json:"shareable"`
SepID int `json:"sepId"` // NOTE: absent from compute/get output
SizeMax int `json:"sizeMax"`
SizeUsed int `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
SizeUsed float64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
Snapshots []Snapshot `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
@@ -164,7 +165,7 @@ type Unattached struct {
Role string `json:"role"`
SepID int `json:"sepId"`
SizeMax int `json:"sizeMax"`
SizeUsed int `json:"sizeUsed"`
SizeUsed float64 `json:"sizeUsed"`
Snapshots []Snapshot `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
@@ -173,3 +174,8 @@ type Unattached struct {
}
type UnattachedList []Unattached
type Pair struct {
intPort int
extPortStart int
}

View File

@@ -42,6 +42,7 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/dc"
"github.com/rudecs/terraform-provider-decort/internal/status"
log "github.com/sirupsen/logrus"
@@ -112,6 +113,15 @@ func resourceDiskCreate(ctx context.Context, d *schema.ResourceData, m interface
urlValues = &url.Values{}
}
if shareable := d.Get("shareable"); shareable.(bool) == true {
urlValues.Add("diskId", diskId)
_, err := c.DecortAPICall(ctx, "POST", disksShareAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
dgn := resourceDiskRead(ctx, d, m)
if dgn != nil {
return dgn
@@ -123,6 +133,7 @@ func resourceDiskCreate(ctx context.Context, d *schema.ResourceData, m interface
func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
urlValues := &url.Values{}
c := m.(*controller.ControllerCfg)
warnings := dc.Warnings{}
disk, err := utilityDiskCheckPresence(ctx, d, m)
if disk == nil {
@@ -133,17 +144,21 @@ func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}
return nil
}
hasChangeState := false
if disk.Status == status.Destroyed || disk.Status == status.Purged {
d.Set("disk_id", 0)
return resourceDiskCreate(ctx, d, m)
} else if disk.Status == status.Deleted {
hasChangeState = true
urlValues.Add("diskId", d.Id())
urlValues.Add("reason", d.Get("reason").(string))
_, err := c.DecortAPICall(ctx, "POST", disksRestoreAPI, urlValues)
if err != nil {
return diag.FromErr(err)
warnings.Add(err)
}
}
if hasChangeState {
urlValues = &url.Values{}
disk, err = utilityDiskCheckPresence(ctx, d, m)
if disk == nil {
@@ -161,8 +176,7 @@ func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}
d.Set("account_name", disk.AccountName)
d.Set("acl", string(diskAcl))
d.Set("boot_partition", disk.BootPartition)
d.Set("compute_id", disk.ComputeID)
d.Set("compute_name", disk.ComputeName)
d.Set("computes", flattenDiskComputes(disk.Computes))
d.Set("created_time", disk.CreatedTime)
d.Set("deleted_time", disk.DeletedTime)
d.Set("desc", disk.Desc)
@@ -185,6 +199,7 @@ func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}
d.Set("passwd", disk.Passwd)
d.Set("pci_slot", disk.PciSlot)
d.Set("pool", disk.Pool)
d.Set("present_to", disk.PresentTo)
d.Set("purge_attempts", disk.PurgeAttempts)
d.Set("purge_time", disk.PurgeTime)
d.Set("reality_device_number", disk.RealityDeviceNumber)
@@ -196,13 +211,14 @@ func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}
d.Set("sep_type", disk.SepType)
d.Set("size_max", disk.SizeMax)
d.Set("size_used", disk.SizeUsed)
d.Set("shareable", disk.Shareable)
d.Set("snapshots", flattenDiskSnapshotList(disk.Snapshots))
d.Set("status", disk.Status)
d.Set("tech_status", disk.TechStatus)
d.Set("type", disk.Type)
d.Set("vmid", disk.VMID)
return nil
return warnings.Get()
}
func resourceDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -215,18 +231,6 @@ func resourceDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface
}
return nil
}
if disk.Status == status.Destroyed || disk.Status == status.Purged {
return resourceDiskCreate(ctx, d, m)
} else if disk.Status == status.Deleted {
urlValues.Add("diskId", d.Id())
urlValues.Add("reason", d.Get("reason").(string))
_, err := c.DecortAPICall(ctx, "POST", disksRestoreAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("size_max") {
oldSize, newSize := d.GetChange("size_max")
@@ -283,6 +287,24 @@ func resourceDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface
urlValues = &url.Values{}
}
if d.HasChange("shareable") {
oldShare, newShare := d.GetChange("shareable")
urlValues = &url.Values{}
urlValues.Add("diskId", d.Id())
if oldShare.(bool) == false && newShare.(bool) == true {
_, err := c.DecortAPICall(ctx, "POST", disksShareAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
}
if oldShare.(bool) == true && newShare.(bool) == false {
_, err := c.DecortAPICall(ctx, "POST", disksUnshareAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
}
}
return resourceDiskRead(ctx, d, m)
}
@@ -341,6 +363,13 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Pool for disk location",
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
@@ -360,7 +389,6 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
ValidateFunc: validation.StringInSlice([]string{"D", "B", "T"}, false),
Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data, T=Temp'",
},
"detach": {
Type: schema.TypeBool,
Optional: true,
@@ -379,6 +407,11 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Default: "",
Description: "Reason for deletion",
},
"shareable": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"disk_id": {
Type: schema.TypeInt,
@@ -399,15 +432,21 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Number of disk partitions",
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Compute ID",
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
Description: "Compute name",
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeString,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_time": {
Type: schema.TypeInt,
@@ -622,7 +661,7 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Description: "Type SEP. Defines the type of storage system and contains one of the values set in the cloud platform",
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
Description: "Number of used space, in GB",
},

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -80,6 +81,7 @@ func flattenImage(d *schema.ResourceData, img *ImageExtend) {
d.Set("pool_name", img.Pool)
d.Set("provider_name", img.ProviderName)
d.Set("purge_attempts", img.PurgeAttempts)
d.Set("present_to", img.PresentTo)
d.Set("res_id", img.ResId)
d.Set("rescuecd", img.RescueCD)
d.Set("sep_id", img.SepId)

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -161,6 +162,13 @@ func dataSourceImageExtendSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -134,6 +135,7 @@ type ImageExtend struct {
Password string `json:"password"`
Pool string `json:"pool"`
ProviderName string `json:"provider_name"`
PresentTo []int `json:"presentTo"`
PurgeAttempts int `json:"purgeAttempts"`
ResId string `json:"resId"`
RescueCD bool `json:"rescuecd"`

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (
@@ -11,19 +43,6 @@ import (
log "github.com/sirupsen/logrus"
)
func flattenWgData(d *schema.ResourceData, wg K8SGroup, computes []kvmvm.ComputeGetResp) {
d.Set("annotations", wg.Annotations)
d.Set("cpu", wg.CPU)
d.Set("detailed_info", flattenDetailedInfo(wg.DetailedInfo, computes))
d.Set("disk", wg.Disk)
d.Set("guid", wg.GUID)
d.Set("labels", wg.Labels)
d.Set("name", wg.Name)
d.Set("num", wg.Num)
d.Set("ram", wg.RAM)
d.Set("taints", wg.Taints)
}
func dataSourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("dataSourceK8sWgRead: called with k8s id %d", d.Get("k8s_id").(int))

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (
@@ -13,33 +45,6 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm"
)
func flattenWgList(wgList K8SGroupList, computesMap map[uint64][]kvmvm.ComputeGetResp) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, wg := range wgList {
computes := computesMap[wg.ID]
temp := map[string]interface{}{
"annotations": wg.Annotations,
"cpu": wg.CPU,
"wg_id": wg.ID,
"detailed_info": flattenDetailedInfo(wg.DetailedInfo, computes),
"disk": wg.Disk,
"guid": wg.GUID,
"labels": wg.Labels,
"name": wg.Name,
"num": wg.Num,
"ram": wg.RAM,
"taints": wg.Taints,
}
res = append(res, temp)
}
return res
}
func flattenItemsWg(d *schema.ResourceData, wgList K8SGroupList, computes map[uint64][]kvmvm.ComputeGetResp) {
d.Set("items", flattenWgList(wgList, computes))
}
func utilityK8sWgListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (K8SGroupList, error) {
c := m.(*controller.ControllerCfg)

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package k8s
import (
@@ -245,3 +277,43 @@ func flattenResourceK8s(d *schema.ResourceData, k8s K8SRecord, masters []kvmvm.C
d.Set("updated_time", k8s.UpdatedTime)
d.Set("default_wg_id", k8s.K8SGroups.Workers[0].ID)
}
func flattenWgData(d *schema.ResourceData, wg K8SGroup, computes []kvmvm.ComputeGetResp) {
d.Set("annotations", wg.Annotations)
d.Set("cpu", wg.CPU)
d.Set("detailed_info", flattenDetailedInfo(wg.DetailedInfo, computes))
d.Set("disk", wg.Disk)
d.Set("guid", wg.GUID)
d.Set("labels", wg.Labels)
d.Set("name", wg.Name)
d.Set("num", wg.Num)
d.Set("ram", wg.RAM)
d.Set("taints", wg.Taints)
}
func flattenWgList(wgList K8SGroupList, computesMap map[uint64][]kvmvm.ComputeGetResp) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, wg := range wgList {
computes := computesMap[wg.ID]
temp := map[string]interface{}{
"annotations": wg.Annotations,
"cpu": wg.CPU,
"wg_id": wg.ID,
"detailed_info": flattenDetailedInfo(wg.DetailedInfo, computes),
"disk": wg.Disk,
"guid": wg.GUID,
"labels": wg.Labels,
"name": wg.Name,
"num": wg.Num,
"ram": wg.RAM,
"taints": wg.Taints,
}
res = append(res, temp)
}
return res
}
func flattenItemsWg(d *schema.ResourceData, wgList K8SGroupList, computes map[uint64][]kvmvm.ComputeGetResp) {
d.Set("items", flattenWgList(wgList, computes))
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -48,6 +49,8 @@ type K8sNodeRecord struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"detailedInfo"`
SepID int `json:"SepId"`
SepPool string `json:"SepPool"`
}
//K8sRecord represents k8s instance

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -55,10 +56,12 @@ func parseNode(nodeList []interface{}) K8sNodeRecord {
node := nodeList[0].(map[string]interface{})
return K8sNodeRecord{
Num: node["num"].(int),
Cpu: node["cpu"].(int),
Ram: node["ram"].(int),
Disk: node["disk"].(int),
Num: node["num"].(int),
Cpu: node["cpu"].(int),
Ram: node["ram"].(int),
Disk: node["disk"].(int),
SepID: node["sep_id"].(int),
SepPool: node["sep_pool"].(string),
}
}
@@ -111,6 +114,14 @@ func mastersSchemaMake() map[string]*schema.Schema {
Required: true,
Description: "Number of nodes to create.",
}
masters["sep_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
}
masters["sep_pool"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
}
masters["cpu"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
@@ -139,6 +150,14 @@ func workersSchemaMake() map[string]*schema.Schema {
Required: true,
Description: "Number of nodes to create.",
}
workers["sep_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
}
workers["sep_pool"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
}
workers["cpu"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -68,6 +69,8 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
urlValues.Add("masterCpu", strconv.Itoa(masterNode.Cpu))
urlValues.Add("masterRam", strconv.Itoa(masterNode.Ram))
urlValues.Add("masterDisk", strconv.Itoa(masterNode.Disk))
urlValues.Add("masterSepId", strconv.Itoa(masterNode.SepID))
urlValues.Add("masterSepPool", masterNode.SepPool)
var workerNode K8sNodeRecord
if workers, ok := d.GetOk("workers"); ok {
@@ -79,6 +82,29 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
urlValues.Add("workerCpu", strconv.Itoa(workerNode.Cpu))
urlValues.Add("workerRam", strconv.Itoa(workerNode.Ram))
urlValues.Add("workerDisk", strconv.Itoa(workerNode.Disk))
urlValues.Add("workerSepId", strconv.Itoa(workerNode.SepID))
urlValues.Add("workerSepPool", workerNode.SepPool)
if labels, ok := d.GetOk("labels"); ok {
labels := labels.([]interface{})
for _, label := range labels {
urlValues.Add("labels", label.(string))
}
}
if taints, ok := d.GetOk("taints"); ok {
taints := taints.([]interface{})
for _, taint := range taints {
urlValues.Add("taints", taint.(string))
}
}
if annotations, ok := d.GetOk("annotations"); ok {
annotations := annotations.([]interface{})
for _, annotation := range annotations {
urlValues.Add("annotations", annotation.(string))
}
}
if withLB, ok := d.GetOk("with_lb"); ok {
urlValues.Add("withLB", strconv.FormatBool(withLB.(bool)))
@@ -132,7 +158,6 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
}
func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
//log.Debugf("resourceK8sRead: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityDataK8sCheckPresence(ctx, d, m)
if err != nil {
@@ -281,28 +306,45 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
Required: true,
Description: "Name of the cluster.",
},
"rg_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "Resource group ID that this instance belongs to.",
},
"k8sci_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "ID of the k8s catalog item to base this instance on.",
},
"wg_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Name for first worker group created with cluster.",
},
"labels": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"taints": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"annotations": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"masters": {
Type: schema.TypeList,
Optional: true,
@@ -314,7 +356,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
},
Description: "Master node(s) configuration.",
},
"workers": {
Type: schema.TypeList,
Optional: true,
@@ -325,7 +366,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
},
Description: "Worker node(s) configuration.",
},
"with_lb": {
Type: schema.TypeBool,
Optional: true,
@@ -333,7 +373,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
Default: true,
Description: "Create k8s with load balancer if true.",
},
"extnet_id": {
Type: schema.TypeInt,
Optional: true,
@@ -341,7 +380,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
ForceNew: true,
Description: "ID of the external network to connect workers to. If omitted network will be chosen by the platfom.",
},
"desc": {
Type: schema.TypeString,
Optional: true,
@@ -416,13 +454,11 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"default_wg_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of default workers group for this instace.",
},
"kubeconfig": {
Type: schema.TypeString,
Computed: true,

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -52,4 +52,14 @@ const (
ComputeRestoreAPI = "/restmachine/cloudapi/compute/restore"
ComputeEnableAPI = "/restmachine/cloudapi/compute/enable"
ComputeDisableAPI = "/restmachine/cloudapi/compute/disable"
//affinity and anti-affinity
ComputeAffinityLabelSetAPI = "/restmachine/cloudapi/compute/affinityLabelSet"
ComputeAffinityLabelRemoveAPI = "/restmachine/cloudapi/compute/affinityLabelRemove"
ComputeAffinityRuleAddAPI = "/restmachine/cloudapi/compute/affinityRuleAdd"
ComputeAffinityRuleRemoveAPI = "/restmachine/cloudapi/compute/affinityRuleRemove"
ComputeAffinityRulesClearAPI = "/restmachine/cloudapi/compute/affinityRulesClear"
ComputeAntiAffinityRuleAddAPI = "/restmachine/cloudapi/compute/antiAffinityRuleAdd"
ComputeAntiAffinityRuleRemoveAPI = "/restmachine/cloudapi/compute/antiAffinityRuleRemove"
ComputeAntiAffinityRulesClearAPI = "/restmachine/cloudapi/compute/antiAffinityRulesClear"
)

View File

@@ -45,7 +45,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
@@ -125,10 +124,10 @@ func findInExtraDisks(DiskId uint, ExtraDisks []interface{}) bool {
return false
}
func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) []map[string]interface{} {
func flattenDataComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range disksList {
if disk.Name == "bootdisk" || findInExtraDisks(disk.ID, extraDisks) { //skip main bootdisk and extraDisks
if findInExtraDisks(disk.ID, extraDisks) { //skip main bootdisk and extraDisks
continue
}
temp := map[string]interface{}{
@@ -136,6 +135,9 @@ func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) [
"disk_id": disk.ID,
"disk_type": disk.Type,
"sep_id": disk.SepID,
"shareable": disk.Shareable,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"pool": disk.Pool,
"desc": disk.Desc,
"image_id": disk.ImageID,
@@ -146,7 +148,7 @@ func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) [
return res
}
func flattenCompute(d *schema.ResourceData, compFacts string) error {
func flattenDataCompute(d *schema.ResourceData, compFacts string) error {
// This function expects that compFacts string contains response from API compute/get,
// i.e. detailed information about compute instance.
//
@@ -183,7 +185,7 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
d.Set("enabled", true)
}
d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion
//d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion
// d.Set("status", model.Status)
// d.Set("tech_status", model.TechStatus)
d.Set("started", false)
@@ -219,7 +221,7 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
}
}
err = d.Set("disks", flattenComputeDisksDemo(model.Disks, d.Get("extra_disks").(*schema.Set).List()))
err = d.Set("disks", flattenDataComputeDisksDemo(model.Disks, d.Get("extra_disks").(*schema.Set).List()))
if err != nil {
return err
}
@@ -236,7 +238,7 @@ func dataSourceComputeRead(ctx context.Context, d *schema.ResourceData, m interf
return diag.FromErr(err)
}
if err = flattenCompute(d, compFacts); err != nil {
if err = flattenDataCompute(d, compFacts); err != nil {
return diag.FromErr(err)
}
@@ -353,48 +355,53 @@ func DataSourceCompute() *schema.Resource {
"disks": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disk_name": {
Type: schema.TypeString,
Required: true,
Computed: true,
Description: "Name for disk",
},
"size": {
Type: schema.TypeInt,
Required: true,
Computed: true,
Description: "Disk size in GiB",
},
"disk_type": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"B", "D"}, false),
Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data'",
Type: schema.TypeString,
Computed: true,
Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data'",
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: "Storage endpoint provider ID; by default the same with boot disk",
},
"shareable": {
Type: schema.TypeBool,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Computed: true,
},
"size_used": {
Type: schema.TypeFloat,
Computed: true,
},
"pool": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: "Pool name; by default will be chosen automatically",
},
"desc": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: "Optional description",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: "Specify image id for create disk from template",
},
"disk_id": {
@@ -404,8 +411,7 @@ func DataSourceCompute() *schema.Resource {
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Computed: true,
Description: "Disk deletion status",
},
},

View File

@@ -0,0 +1,115 @@
package kvmvm
import (
"encoding/json"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/status"
log "github.com/sirupsen/logrus"
)
func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range disksList {
if disk.Name == "bootdisk" || findInExtraDisks(disk.ID, extraDisks) { //skip main bootdisk and extraDisks
continue
}
temp := map[string]interface{}{
"disk_name": disk.Name,
"disk_id": disk.ID,
"disk_type": disk.Type,
"sep_id": disk.SepID,
"shareable": disk.Shareable,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"pool": disk.Pool,
"desc": disk.Desc,
"image_id": disk.ImageID,
"size": disk.SizeMax,
}
res = append(res, temp)
}
return res
}
func flattenCompute(d *schema.ResourceData, compFacts string) error {
// This function expects that compFacts string contains response from API compute/get,
// i.e. detailed information about compute instance.
//
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceComputeExists(...) method
model := ComputeGetResp{}
log.Debugf("flattenCompute: ready to unmarshal string %s", compFacts)
err := json.Unmarshal([]byte(compFacts), &model)
if err != nil {
return err
}
log.Debugf("flattenCompute: ID %d, RG ID %d", model.ID, model.RgID)
d.SetId(fmt.Sprintf("%d", model.ID))
// d.Set("compute_id", model.ID) - we should NOT set compute_id in the schema here: if it was set - it is already set, if it wasn't - we shouldn't
d.Set("name", model.Name)
d.Set("rg_id", model.RgID)
d.Set("rg_name", model.RgName)
d.Set("account_id", model.AccountID)
d.Set("account_name", model.AccountName)
d.Set("driver", model.Driver)
d.Set("cpu", model.Cpu)
d.Set("ram", model.Ram)
// d.Set("boot_disk_size", model.BootDiskSize) - bootdiskSize key in API compute/get is always zero, so we set boot_disk_size in another way
if model.VirtualImageID != 0 {
d.Set("image_id", model.VirtualImageID)
} else {
d.Set("image_id", model.ImageID)
}
d.Set("description", model.Desc)
d.Set("enabled", false)
if model.Status == status.Enabled {
d.Set("enabled", true)
}
//d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion
//d.Set("status", model.Status)
//d.Set("tech_status", model.TechStatus)
d.Set("started", false)
if model.TechStatus == "STARTED" {
d.Set("started", true)
}
bootDisk := findBootDisk(model.Disks)
d.Set("boot_disk_size", bootDisk.SizeMax)
d.Set("boot_disk_id", bootDisk.ID) // we may need boot disk ID in resize operations
d.Set("sep_id", bootDisk.SepID)
d.Set("pool", bootDisk.Pool)
//if len(model.Disks) > 0 {
//log.Debugf("flattenCompute: calling parseComputeDisksToExtraDisks for %d disks", len(model.Disks))
//if err = d.Set("extra_disks", parseComputeDisksToExtraDisks(model.Disks)); err != nil {
//return err
//}
//}
if len(model.Interfaces) > 0 {
log.Debugf("flattenCompute: calling parseComputeInterfacesToNetworks for %d interfaces", len(model.Interfaces))
if err = d.Set("network", parseComputeInterfacesToNetworks(model.Interfaces)); err != nil {
return err
}
}
if len(model.OsUsers) > 0 {
log.Debugf("flattenCompute: calling parseOsUsers for %d logins", len(model.OsUsers))
if err = d.Set("os_users", parseOsUsers(model.OsUsers)); err != nil {
return err
}
}
err = d.Set("disks", flattenComputeDisksDemo(model.Disks, d.Get("extra_disks").(*schema.Set).List()))
if err != nil {
return err
}
return nil
}

View File

@@ -72,8 +72,9 @@ type DiskRecord struct {
Role string `json:"role"`
SepType string `json:"sepType"`
SepID int `json:"sepId"` // NOTE: absent from compute/get output
Shareable bool `json:"shareable"`
SizeMax int `json:"sizeMax"`
SizeUsed int `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
SizeUsed float64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
Snapshots []SnapshotRecord `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`

View File

@@ -225,6 +225,18 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
}
if !cleanup {
if affinityLabel, ok := d.GetOk("affinity_label"); ok {
affinityLabel := affinityLabel.(string)
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("affinityLabel", affinityLabel)
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityLabelSetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if disks, ok := d.GetOk("disks"); ok {
log.Debugf("resourceComputeCreate: Create disks on ComputeID: %d", compId)
addedDisks := disks.([]interface{})
@@ -259,6 +271,52 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
}
}
}
if ars, ok := d.GetOk("affinity_rules"); ok {
log.Debugf("resourceComputeCreate: Create affinity rules on ComputeID: %d", compId)
addedAR := ars.([]interface{})
if len(addedAR) > 0 {
for _, ar := range addedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityRuleAddAPI, urlValues)
if err != nil {
cleanup = true
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
}
if ars, ok := d.GetOk("anti_affinity_rules"); ok {
log.Debugf("resourceComputeCreate: Create anti affinity rules on ComputeID: %d", compId)
addedAR := ars.([]interface{})
if len(addedAR) > 0 {
for _, ar := range addedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAntiAffinityRuleAddAPI, urlValues)
if err != nil {
cleanup = true
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
}
}
log.Debugf("resourceComputeCreate: new Compute ID %d, name %s creation sequence complete", compId, d.Get("name").(string))
@@ -576,6 +634,155 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
}
}
if d.HasChange("affinity_label") {
affinityLabel := d.Get("affinity_label").(string)
urlValues.Add("computeId", d.Id())
if affinityLabel == "" {
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityLabelRemoveAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
}
urlValues.Add("affinityLabel", affinityLabel)
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityLabelSetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("affinity_rules") {
deletedAR := make([]interface{}, 0)
addedAR := make([]interface{}, 0)
oldAR, newAR := d.GetChange("affinity_rules")
oldConv := oldAR.([]interface{})
newConv := newAR.([]interface{})
if len(newConv) == 0 {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityRulesClearAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
} else {
for _, el := range oldConv {
if !isContainsAR(newConv, el) {
deletedAR = append(deletedAR, el)
}
}
for _, el := range newConv {
if !isContainsAR(oldConv, el) {
addedAR = append(addedAR, el)
}
}
if len(deletedAR) > 0 {
urlValues := &url.Values{}
for _, ar := range deletedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityRuleRemoveAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
if len(addedAR) > 0 {
for _, ar := range addedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAffinityRuleAddAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
}
}
if d.HasChange("anti_affinity_rules") {
deletedAR := make([]interface{}, 0)
addedAR := make([]interface{}, 0)
oldAR, newAR := d.GetChange("anti_affinity_rules")
oldConv := oldAR.([]interface{})
newConv := newAR.([]interface{})
if len(newConv) == 0 {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", ComputeAntiAffinityRulesClearAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
} else {
for _, el := range oldConv {
if !isContainsAR(newConv, el) {
deletedAR = append(deletedAR, el)
}
}
for _, el := range newConv {
if !isContainsAR(oldConv, el) {
addedAR = append(addedAR, el)
}
}
if len(deletedAR) > 0 {
urlValues := &url.Values{}
for _, ar := range deletedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAntiAffinityRuleRemoveAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
if len(addedAR) > 0 {
for _, ar := range addedAR {
arConv := ar.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("topology", arConv["topology"].(string))
urlValues.Add("policy", arConv["policy"].(string))
urlValues.Add("mode", arConv["mode"].(string))
urlValues.Add("key", arConv["key"].(string))
urlValues.Add("value", arConv["value"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeAntiAffinityRuleAddAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
}
}
// we may reuse dataSourceComputeRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return resourceComputeRead(ctx, d, m)
@@ -592,6 +799,21 @@ func isContainsDisk(els []interface{}, el interface{}) bool {
return false
}
func isContainsAR(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})
elConv := el.(map[string]interface{})
if elOldConv["key"].(string) == elConv["key"].(string) &&
elOldConv["value"].(string) == elConv["value"].(string) &&
elOldConv["mode"].(string) == elConv["mode"].(string) &&
elOldConv["topology"].(string) == elConv["topology"].(string) &&
elOldConv["policy"].(string) == elConv["policy"].(string) {
return true
}
}
return false
}
func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// NOTE: this function destroys target Compute instance "permanently", so
// there is no way to restore it.
@@ -665,6 +887,86 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema {
Description: "This compute instance boot disk size in GB. Make sure it is large enough to accomodate selected OS image.",
},
"affinity_label": {
Type: schema.TypeString,
Optional: true,
Description: "Set affinity label for compute",
},
"affinity_rules": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topology": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"node", "compute"}, false),
Description: "compute or node, for whom rule applies",
},
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"RECOMMENDED", "REQUIRED"}, false),
Description: "RECOMMENDED or REQUIRED, the degree of 'strictness' of this rule",
},
"mode": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"EQ", "NE", "ANY"}, false),
Description: "EQ or NE or ANY - the comparison mode is 'value', recorded by the specified 'key'",
},
"key": {
Type: schema.TypeString,
Required: true,
Description: "key that are taken into account when analyzing this rule will be identified",
},
"value": {
Type: schema.TypeString,
Required: true,
Description: "value that must match the key to be taken into account when analyzing this rule",
},
},
},
},
"anti_affinity_rules": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topology": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"node", "compute"}, false),
Description: "compute or node, for whom rule applies",
},
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"RECOMMENDED", "REQUIRED"}, false),
Description: "RECOMMENDED or REQUIRED, the degree of 'strictness' of this rule",
},
"mode": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"EQ", "NE", "ANY"}, false),
Description: "EQ or NE or ANY - the comparison mode is 'value', recorded by the specified 'key'",
},
"key": {
Type: schema.TypeString,
Required: true,
Description: "key that are taken into account when analyzing this rule will be identified",
},
"value": {
Type: schema.TypeString,
Required: true,
Description: "value that must match the key to be taken into account when analyzing this rule",
},
},
},
},
"disks": {
Type: schema.TypeList,
Computed: true,
@@ -694,6 +996,18 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema {
Optional: true,
Description: "Storage endpoint provider ID; by default the same with boot disk",
},
"shareable": {
Type: schema.TypeBool,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Computed: true,
},
"size_used": {
Type: schema.TypeFloat,
Computed: true,
},
"pool": {
Type: schema.TypeString,
Computed: true,
@@ -782,11 +1096,11 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema {
},
"cloud_init": {
Type: schema.TypeString,
Optional: true,
Default: "applied",
DiffSuppressFunc: cloudInitDiffSupperss,
Description: "Optional cloud_init parameters. Applied when creating new compute instance only, ignored in all other cases.",
Type: schema.TypeString,
Optional: true,
Description: "Optional cloud_init parameters. Applied when creating new compute instance only, ignored in all other cases.",
//Default: "applied",
//DiffSuppressFunc: cloudInitDiffSupperss,
},
"enabled": {

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,10 +35,11 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
"github.com/rudecs/terraform-provider-decort/internal/controller"
// "net/url"
@@ -45,53 +47,31 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
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.Debugf("%s", rg_facts)
log.Debugf("flattenResgroup: ready to decode response body from API")
details := ResgroupGetResp{}
err := json.Unmarshal([]byte(rg_facts), &details)
func utilityDataResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ResgroupGetResp, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgData := &ResgroupGetResp{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil {
return err
return nil, err
}
log.Debugf("flattenResgroup: decoded RG name %q / ID %d, account ID %d",
details.Name, details.ID, details.AccountID)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("rg_id", details.ID)
d.Set("name", details.Name)
d.Set("account_name", details.AccountName)
d.Set("account_id", details.AccountID)
// d.Set("grid_id", details.GridID)
d.Set("description", details.Desc)
d.Set("status", details.Status)
d.Set("def_net_type", details.DefaultNetType)
d.Set("def_net_id", details.DefaultNetID)
/*
d.Set("vins", details.Vins)
d.Set("computes", details.Computes)
*/
log.Debugf("flattenResgroup: calling flattenQuota()")
if err = d.Set("quota", parseQuota(details.Quota)); err != nil {
return err
err = json.Unmarshal([]byte(rgRaw), rgData)
if err != nil {
return nil, err
}
return nil
return rgData, nil
}
func dataSourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
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
rg, err := utilityDataResgroupCheckPresence(ctx, d, m)
if err != nil {
d.SetId("") // ensure ID is empty in this case
return diag.FromErr(err)
}
return diag.FromErr(flattenResgroup(d, rg_facts))
return diag.FromErr(flattenDataResgroup(d, *rg))
}
func DataSourceResgroup() *schema.Resource {
@@ -126,7 +106,7 @@ func DataSourceResgroup() *schema.Resource {
"account_id": {
Type: schema.TypeInt,
Required: true,
Optional: true,
Description: "Unique ID of the account, which this resource group belongs to.",
},
@@ -135,15 +115,11 @@ func DataSourceResgroup() *schema.Resource {
Computed: true,
Description: "User-defined text description of this resource group.",
},
/* commented out, as in this version of provider we use default Grid ID
"grid_id": {
"gid": {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the grid, where this resource group is deployed.",
},
*/
"quota": {
Type: schema.TypeList,
Computed: true,
@@ -165,32 +141,150 @@ func DataSourceResgroup() *schema.Resource {
Description: "ID of the default network for this resource group (if any).",
},
/*
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this resource group.",
},
"vins": {
Type: schema.TypeList, // this is a list of ints
Computed: true,
MaxItems: LimitMaxVinsPerResgroup,
Elem: &schema.Schema{
Type: schema.TypeInt,
"resources": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"current": {
Type: schema.TypeList,
Computed: true,
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,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
"reserved": {
Type: schema.TypeList,
Computed: true,
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,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
},
Description: "List of VINs deployed in this resource group.",
},
},
"computes": {
Type: schema.TypeList, //t his is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of computes deployed in this resource group.",
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this resource group.",
},
"vins": {
Type: schema.TypeList, // this is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
*/
Description: "List of VINs deployed in this resource group.",
},
"vms": {
Type: schema.TypeList, //t his is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of computes deployed in this resource group.",
},
},
}
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,145 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package rg
import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
)
func flattenAccountSeps(seps map[string]map[string]ResourceSep) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for sepKey, sepVal := range seps {
for dataKey, dataVal := range sepVal {
temp := map[string]interface{}{
"sep_id": sepKey,
"data_name": dataKey,
"disk_size": dataVal.DiskSize,
"disk_size_max": dataVal.DiskSizeMax,
}
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,
"seps": flattenAccountSeps(r.SEPs),
}
res = append(res, temp)
return res
}
func flattenRgResources(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 flattenDataResgroup(d *schema.ResourceData, details ResgroupGetResp) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceRsgroupExists(...) method
// log.Debugf("%s", rg_facts)
log.Debugf("flattenResgroup: decoded RG name %q / ID %d, account ID %d",
details.Name, details.ID, details.AccountID)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("rg_id", details.ID)
d.Set("name", details.Name)
d.Set("account_name", details.AccountName)
d.Set("account_id", details.AccountID)
d.Set("gid", details.GridID)
d.Set("description", details.Desc)
d.Set("status", details.Status)
d.Set("def_net_type", details.DefaultNetType)
d.Set("def_net_id", details.DefaultNetID)
d.Set("resources", flattenRgResources(details.Resources))
d.Set("vins", details.Vins)
d.Set("vms", details.Computes)
log.Debugf("flattenResgroup: calling flattenQuota()")
if err := d.Set("quota", parseQuota(details.Quota)); err != nil {
return err
}
return nil
}
func flattenResgroup(d *schema.ResourceData, details ResgroupGetResp) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceRsgroupExists(...) method
// log.Debugf("%s", rg_facts)
//log.Debugf("flattenResgroup: ready to decode response body from API")
//details := ResgroupGetResp{}
//err := json.Unmarshal([]byte(rg_facts), &details)
//if err != nil {
//return err
//}
log.Debugf("flattenResgroup: decoded RG name %q / ID %d, account ID %d",
details.Name, details.ID, details.AccountID)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("rg_id", details.ID)
d.Set("name", details.Name)
d.Set("account_name", details.AccountName)
d.Set("account_id", details.AccountID)
d.Set("gid", details.GridID)
d.Set("description", details.Desc)
d.Set("status", details.Status)
d.Set("def_net_type", details.DefaultNetType)
d.Set("def_net_id", details.DefaultNetID)
d.Set("resources", flattenRgResources(details.Resources))
d.Set("vins", details.Vins)
d.Set("vms", details.Computes)
log.Debugf("flattenResgroup: calling flattenQuota()")
if err := d.Set("quota", parseQuota(details.Quota)); err != nil {
return err
}
return nil
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -91,27 +92,28 @@ type AccountAclRecord struct {
}
type ResgroupGetResp struct {
ACLs []UserAclRecord `json:"ACLs"`
Usage UsageRecord `json:"Resources"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
GridID int `json:"gid"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
DefaultNetType string `json:"def_net_type"`
DeletedBy string `json:"deletedBy"`
DeletedTime uint64 `json:"deletedTime"`
Desc string `json:"desc"`
ID uint `json:"id"`
LockStatus string `json:"lockStatus"`
Name string `json:"name"`
Quota QuotaRecord `json:"resourceLimits"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"`
Vins []int `json:"vins"`
Computes []int `json:"vms"`
Resources Resources `json:"Resources"`
ACLs []UserAclRecord `json:"ACLs"`
//Usage UsageRecord `json:"Resources"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
GridID int `json:"gid"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
DefaultNetType string `json:"def_net_type"`
DeletedBy string `json:"deletedBy"`
DeletedTime uint64 `json:"deletedTime"`
Desc string `json:"desc"`
ID uint `json:"id"`
LockStatus string `json:"lockStatus"`
Name string `json:"name"`
Quota QuotaRecord `json:"resourceLimits"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"`
Vins []int `json:"vins"`
Computes []int `json:"vms"`
Ignored map[string]interface{} `json:"-"`
}
@@ -135,15 +137,35 @@ type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get
}
type ResourceRecord struct { // this is how actual usage is reported by /api/.../rg/get
Cpu int `json:"cpu"`
Disk int `json:"disksize"`
ExtIPs int `json:"extips"`
ExtTraffic int `json:"exttraffic"`
Gpu int `json:"gpu"`
Ram int `json:"ram"`
Cpu int `json:"cpu"`
Disk float64 `json:"disksize"`
ExtIPs int `json:"extips"`
ExtTraffic int `json:"exttraffic"`
Gpu int `json:"gpu"`
Ram int `json:"ram"`
}
type UsageRecord struct {
Current ResourceRecord `json:"Current"`
Reserved ResourceRecord `json:"Reserved"`
}
type ResourceSep struct {
DiskSize float64 `json:"disksize"`
DiskSizeMax int `json:"disksizemax"`
}
type Resource struct {
CPU int `json:"cpu"`
Disksize float64 `json:"disksize"`
Extips int `json:"extips"`
Exttraffic int `json:"exttraffic"`
GPU int `json:"gpu"`
RAM int `json:"ram"`
SEPs map[string]map[string]ResourceSep `json:"seps"`
}
type Resources struct {
Current Resource `json:"Current"`
Reserved Resource `json:"Reserved"`
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,9 +34,9 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
@@ -133,16 +134,11 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
d.SetId(api_resp) // rg/create API returns ID of the newly creted resource group on success
// rg.ID, _ = strconv.Atoi(api_resp)
if !set_quota {
resp, err := utilityResgroupCheckPresence(ctx, d, m)
rg, err := utilityResgroupCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
rg := ResgroupGetResp{}
if err := json.Unmarshal([]byte(resp), &rg); err != nil {
return diag.FromErr(err)
}
d.Set("quota", parseQuota(rg.Quota))
}
@@ -155,14 +151,14 @@ func resourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interfa
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
if rg_facts == "" {
if err != nil {
// 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
return diag.FromErr(err)
}
return diag.FromErr(flattenResgroup(d, rg_facts))
return diag.FromErr(flattenResgroup(d, *rg_facts))
}
func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -272,24 +268,21 @@ func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m inter
log.Debugf("resourceResgroupDelete: called for RG name %s, account ID %d",
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
if rg_facts == "" {
if err != nil {
return diag.FromErr(err)
}
// the target RG does not exist - in this case according to Terraform best practice
// we exit from Destroy method without error
return nil
c := m.(*controller.ControllerCfg)
url_values := &url.Values{}
url_values.Add("rgId", d.Id())
if force, ok := d.GetOk("force"); ok {
url_values.Add("force", strconv.FormatBool(force.(bool)))
}
if permanently, ok := d.GetOk("permanently"); ok {
url_values.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
if reason, ok := d.GetOk("reason"); ok {
url_values.Add("reason", reason.(string))
}
url_values := &url.Values{}
url_values.Add("rgId", d.Id())
url_values.Add("force", "1")
url_values.Add("permanently", "1")
url_values.Add("reason", "Destroyed by DECORT Terraform provider")
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", ResgroupDeleteAPI, url_values)
_, err := c.DecortAPICall(ctx, "POST", ResgroupDeleteAPI, url_values)
if err != nil {
return diag.FromErr(err)
}
@@ -297,6 +290,257 @@ func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m inter
return nil
}
func ResourceRgSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Unique ID of the account, which this resource group belongs to.",
},
"gid": {
Type: schema.TypeInt,
Required: true,
ForceNew: true, // change of Grid ID will require new RG
Description: "Unique ID of the grid, where this resource group is deployed.",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of this resource group. Names are case sensitive and unique within the context of a account.",
},
"def_net_type": {
Type: schema.TypeString,
Optional: true,
Default: "PRIVATE",
ValidateFunc: validation.StringInSlice([]string{"PRIVATE", "PUBLIC", "NONE"}, false),
Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.",
},
"def_net_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the default network for this resource group (if any).",
},
"ipcidr": {
Type: schema.TypeString,
Optional: true,
Description: "Address of the netowrk inside the private network segment (aka ViNS) if def_net_type=PRIVATE",
},
"ext_net_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "ID of the external network for default ViNS. Pass 0 if def_net_type=PUBLIC or no external connection required for the defult ViNS when def_net_type=PRIVATE",
},
"ext_ip": {
Type: schema.TypeString,
Optional: true,
Description: "IP address on the external netowrk to request when def_net_type=PRIVATE and ext_net_id is not 0",
},
"quota": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(),
},
Description: "Quota settings for this resource group.",
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "User-defined text description of this resource group.",
},
"force": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Set to True if you want force delete non-empty RG",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Set to True if you want force delete non-empty RG",
},
"reason": {
Type: schema.TypeString,
Optional: true,
Description: "Set to True if you want force delete non-empty RG",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account, which this resource group belongs to.",
},
"resources": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"current": {
Type: schema.TypeList,
Computed: true,
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,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
"reserved": {
Type: schema.TypeList,
Computed: true,
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,
},
"seps": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"data_name": {
Type: schema.TypeString,
Computed: true,
},
"disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
},
},
},
},
},
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this resource group.",
},
"vins": {
Type: schema.TypeList, //this is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of VINs deployed in this resource group.",
},
"vms": {
Type: schema.TypeList, //t his is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of computes deployed in this resource group.",
},
"computes": {
Type: schema.TypeList, //this is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of computes deployed in this resource group.",
},
}
}
func ResourceResgroup() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
@@ -318,113 +562,6 @@ func ResourceResgroup() *schema.Resource {
Default: &constants.Timeout300s,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of this resource group. Names are case sensitive and unique within the context of a account.",
},
"account_id": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Unique ID of the account, which this resource group belongs to.",
},
"def_net_type": {
Type: schema.TypeString,
Optional: true,
Default: "PRIVATE",
ValidateFunc: validation.StringInSlice([]string{"PRIVATE", "PUBLIC", "NONE"}, false),
Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.",
},
"def_net_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the default network for this resource group (if any).",
},
"ipcidr": {
Type: schema.TypeString,
Optional: true,
Description: "Address of the netowrk inside the private network segment (aka ViNS) if def_net_type=PRIVATE",
},
"ext_net_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "ID of the external network for default ViNS. Pass 0 if def_net_type=PUBLIC or no external connection required for the defult ViNS when def_net_type=PRIVATE",
},
"ext_ip": {
Type: schema.TypeString,
Optional: true,
Description: "IP address on the external netowrk to request when def_net_type=PRIVATE and ext_net_id is not 0",
},
/* commented out, as in this version of provider we use default Grid ID
"grid_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0, // if 0 is passed, default Grid ID will be used
// DefaultFunc: utilityResgroupGetDefaultGridID,
ForceNew: true, // change of Grid ID will require new RG
Description: "Unique ID of the grid, where this resource group is deployed.",
},
*/
"quota": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(),
},
Description: "Quota settings for this resource group.",
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "User-defined text description of this resource group.",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account, which this resource group belongs to.",
},
/*
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this resource group.",
},
"vins": {
Type: schema.TypeList, // this is a list of ints
Computed: true,
MaxItems: LimitMaxVinsPerResgroup,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of VINs deployed in this resource group.",
},
"computes": {
Type: schema.TypeList, // this is a list of ints
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of computes deployed in this resource group.",
},
*/
},
Schema: ResourceRgSchemaMake(),
}
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,19 +35,17 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// On success this function returns a string, as returned by API rg/get, which could be unmarshalled
// into ResgroupGetResp structure
func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ResgroupGetResp, error) {
// This function tries to locate resource group by one of the following algorithms depending
// on the parameters passed:
// - if resource group ID is specified -> by RG ID
@@ -67,73 +66,21 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with RG ID set so
// that Import of RG resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
rgId, argSet := d.GetOk("rg_id")
if argSet {
theId = rgId.(int)
idSet = true
}
if d.Id() != "" {
urlValues.Add("rgId", d.Id())
} else {
idSet = true
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
}
if idSet {
// go straight for the RG by its ID
log.Debugf("utilityResgroupCheckPresence: locating RG by its ID %d", theId)
urlValues.Add("rgId", fmt.Sprintf("%d", theId))
rgFacts, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil {
return "", err
}
return rgFacts, nil
}
rgName, argSet := d.GetOk("name")
if !argSet {
// no RG ID and no RG name - we cannot locate resource group in this case
return "", fmt.Errorf("Cannot check resource group presence if name is empty and no resource group ID specified")
}
// Valid account ID is required to locate a resource group
// obtain Account ID by account name - it should not be zero on success
urlValues.Add("includedeleted", "false")
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupListAPI, urlValues)
rgData := &ResgroupGetResp{}
rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil {
return "", err
return nil, err
}
// log.Debugf("%s", apiResp)
log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %s", ResgroupListAPI)
model := ResgroupListResp{}
err = json.Unmarshal([]byte(apiResp), &model)
err = json.Unmarshal([]byte(rgRaw), rgData)
if err != nil {
return "", err
return nil, err
}
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 == 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)
// 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 resource quota settings
reqValues := &url.Values{}
reqValues.Add("rgId", fmt.Sprintf("%d", item.ID))
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, reqValues)
if err != nil {
return "", err
}
return apiResp, nil
}
}
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, d.Get("account_id").(int))
return rgData, nil
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -32,14 +32,27 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
package vins
const VinsListAPI = "/restmachine/cloudapi/vins/list"
const VinsGetAPI = "/restmachine/cloudapi/vins/get"
const VinsSearchAPI = "/restmachine/cloudapi/vins/search"
const VinsCreateInAccountAPI = "/restmachine/cloudapi/vins/createInAccount"
const VinsCreateInRgAPI = "/restmachine/cloudapi/vins/createInRG"
const VinsExtNetConnectAPI = "/restmachine/cloudapi/vins/extNetConnect"
const VinsExtNetDisconnectAPI = "/restmachine/cloudapi/vins/extNetDisconnect"
const VinsDeleteAPI = "/restmachine/cloudapi/vins/delete"
const (
VinsAuditsAPI = "/restmachine/cloudapi/vins/audits"
VinsCreateInAccountAPI = "/restmachine/cloudapi/vins/createInAccount"
VinsCreateInRgAPI = "/restmachine/cloudapi/vins/createInRG"
VinsDeleteAPI = "/restmachine/cloudapi/vins/delete"
VinsDisableAPI = "/restmachine/cloudapi/vins/disable"
VinsEnableAPI = "/restmachine/cloudapi/vins/enable"
VinsExtNetConnectAPI = "/restmachine/cloudapi/vins/extNetConnect"
VinsExtNetDisconnectAPI = "/restmachine/cloudapi/vins/extNetDisconnect"
VinsExtNetListAPI = "/restmachine/cloudapi/vins/extNetList"
VinsGetAPI = "/restmachine/cloudapi/vins/get"
VinsIpListAPI = "/restmachine/cloudapi/vins/ipList"
VinsIpReleaseAPI = "/restmachine/cloudapi/vins/ipRelease"
VinsIpReserveAPI = "/restmachine/cloudapi/vins/ipReserve"
VinsListAPI = "/restmachine/cloudapi/vins/list"
VinsListDeletedAPI = "/restmachine/cloudapi/vins/listDeleted"
VinsNatRuleAddAPI = "/restmachine/cloudapi/vins/natRuleAdd"
VinsNatRuleDelAPI = "/restmachine/cloudapi/vins/natRuleDel"
VinsNatRuleListAPI = "/restmachine/cloudapi/vins/natRuleList"
VinsRestoreAPI = "/restmachine/cloudapi/vins/restore"
VinsSearchAPI = "/restmachine/cloudapi/vins/search"
VinsVnfdevRedeployAPI = "/restmachine/cloudapi/vins/vnfdevRedeploy"
VinsVnfdevRestartAPI = "/restmachine/cloudapi/vins/vnfdevRestart"
)

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,79 +34,863 @@ package vins
import (
"context"
"encoding/json"
"fmt"
"github.com/rudecs/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
// "net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
// vins_facts is a response string from API vins/get
func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceVinsExists(...) method
// log.Debugf("flattenVins: ready to decode response body from API %s", vins_facts)
vinsRecord := VinsRecord{}
err := json.Unmarshal([]byte(vins_facts), &vinsRecord)
func dataSourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vins, err := utilityDataVinsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
log.Debugf("flattenVins: decoded ViNS name:ID %s:%d, account ID %d, RG ID %d",
vinsRecord.Name, vinsRecord.ID, vinsRecord.AccountID, vinsRecord.RgID)
d.SetId(fmt.Sprintf("%d", vinsRecord.ID))
d.Set("name", vinsRecord.Name)
d.Set("account_id", vinsRecord.AccountID)
d.Set("account_name", vinsRecord.AccountName)
d.Set("rg_id", vinsRecord.RgID)
d.Set("description", vinsRecord.Desc)
d.Set("ipcidr", vinsRecord.IPCidr)
noExtNetConnection := true
for _, value := range vinsRecord.VNFs {
if value.Type == "GW" {
log.Debugf("flattenVins: discovered GW VNF ID %d in ViNS ID %d", value.ID, vinsRecord.ID)
extNetID, idOk := value.Config["ext_net_id"] // NOTE: unknown numbers are unmarshalled to float64. This is by design!
extNetIP, ipOk := value.Config["ext_net_ip"]
if idOk && ipOk {
log.Debugf("flattenVins: ViNS ext_net_id=%d, ext_net_ip=%s", int(extNetID.(float64)), extNetIP.(string))
d.Set("ext_ip_addr", extNetIP.(string))
d.Set("ext_net_id", int(extNetID.(float64)))
} else {
return diag.Errorf("Failed to unmarshal VNF GW Config - structure is invalid.")
}
noExtNetConnection = false
break
}
}
if noExtNetConnection {
d.Set("ext_ip_addr", "")
d.Set("ext_net_id", 0)
}
log.Debugf("flattenVins: EXTRA CHECK - schema rg_id=%d, ext_net_id=%d", d.Get("rg_id").(int), d.Get("ext_net_id").(int))
d.SetId(strconv.FormatUint(vins.ID, 10))
flattenVinsData(d, *vins)
return nil
}
func dataSourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
// if empty string is returned from utilityVinsCheckPresence then there is no
// such ViNS and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty in this case
return diag.FromErr(err)
func vnfConfigMGMTSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"ip_addr": {
Type: schema.TypeString,
Computed: true,
},
"password": {
Type: schema.TypeString,
Computed: true,
},
"ssh_key": {
Type: schema.TypeString,
Computed: true,
},
"user": {
Type: schema.TypeString,
Computed: true,
},
}
}
return flattenVins(d, vinsFacts)
func vnfConfigResourcesSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"cpu": {
Type: schema.TypeInt,
Computed: true,
},
"ram": {
Type: schema.TypeInt,
Computed: true,
},
"stack_id": {
Type: schema.TypeInt,
Computed: true,
},
"uuid": {
Type: schema.TypeString,
Computed: true,
},
}
}
func qosSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"e_rate": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"in_brust": {
Type: schema.TypeInt,
Computed: true,
},
"in_rate": {
Type: schema.TypeInt,
Computed: true,
},
}
}
func vnfInterfaceSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"conn_id": {
Type: schema.TypeInt,
Computed: true,
},
"conn_type": {
Type: schema.TypeString,
Computed: true,
},
"def_gw": {
Type: schema.TypeString,
Computed: true,
},
"flipgroup_id": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
},
"listen_ssh": {
Type: schema.TypeBool,
Computed: true,
},
"mac": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"net_id": {
Type: schema.TypeInt,
Computed: true,
},
"net_mask": {
Type: schema.TypeInt,
Computed: true,
},
"net_type": {
Type: schema.TypeString,
Computed: true,
},
"pci_slot": {
Type: schema.TypeInt,
Computed: true,
},
"qos": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: qosSchemaMake(),
},
},
"target": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"vnfs": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
}
}
func vnfConfigSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"mgmt": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfConfigMGMTSchemaMake(),
},
},
"resources": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfConfigResourcesSchemaMake(),
},
},
}
}
func vnfDevSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"_ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the account, which this ViNS belongs to.",
},
"capabilities": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfConfigSchemaMake(),
},
},
"config_saved": {
Type: schema.TypeBool,
Computed: true,
},
"custom_pre_cfg": {
Type: schema.TypeBool,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"vnf_id": {
Type: schema.TypeInt,
Computed: true,
},
"interfaces": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfInterfaceSchemaMake(),
},
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"vnf_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"vins": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
}
}
func vinsComputeSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
}
}
func reservationSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"client_type": {
Type: schema.TypeString,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"domainname": {
Type: schema.TypeString,
Computed: true,
},
"hostname": {
Type: schema.TypeString,
Computed: true,
},
"ip": {
Type: schema.TypeString,
Computed: true,
},
"mac": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
}
}
func dhcpConfigSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"default_gw": {
Type: schema.TypeString,
Computed: true,
},
"dns": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"ip_end": {
Type: schema.TypeString,
Computed: true,
},
"ip_start": {
Type: schema.TypeString,
Computed: true,
},
"lease": {
Type: schema.TypeInt,
Computed: true,
},
"netmask": {
Type: schema.TypeInt,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"reservations": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: reservationSchemaMake(),
},
},
}
}
func devicesPrimarySchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"dev_id": {
Type: schema.TypeInt,
Computed: true,
},
"iface01": {
Type: schema.TypeString,
Computed: true,
},
"iface02": {
Type: schema.TypeString,
Computed: true,
},
}
}
func devicesSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"primary": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: devicesPrimarySchemaMake(),
},
},
}
}
func dhcpSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"_ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: dhcpConfigSchemaMake(),
},
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"devices": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: devicesSchemaMake(),
},
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"dhcp_id": {
Type: schema.TypeInt,
Computed: true,
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"owner_id": {
Type: schema.TypeInt,
Computed: true,
},
"owner_type": {
Type: schema.TypeString,
Computed: true,
},
"pure_virtual": {
Type: schema.TypeBool,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
}
}
func gwConfigSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"default_gw": {
Type: schema.TypeString,
Computed: true,
},
"ext_net_id": {
Type: schema.TypeInt,
Computed: true,
},
"ext_net_ip": {
Type: schema.TypeString,
Computed: true,
},
"ext_netmask": {
Type: schema.TypeInt,
Computed: true,
},
"qos": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: qosSchemaMake(),
},
},
}
}
func gwSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"_ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: gwConfigSchemaMake(),
},
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"devices": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: devicesSchemaMake(),
},
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"gw_id": {
Type: schema.TypeInt,
Computed: true,
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"owner_id": {
Type: schema.TypeInt,
Computed: true,
},
"owner_type": {
Type: schema.TypeString,
Computed: true,
},
"pure_virtual": {
Type: schema.TypeBool,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
}
}
func rulesSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"rule_id": {
Type: schema.TypeInt,
Computed: true,
},
"local_ip": {
Type: schema.TypeString,
Computed: true,
},
"local_port": {
Type: schema.TypeInt,
Computed: true,
},
"protocol": {
Type: schema.TypeString,
Computed: true,
},
"public_port_end": {
Type: schema.TypeInt,
Computed: true,
},
"public_port_start": {
Type: schema.TypeInt,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
},
}
}
func configSchrmaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"net_mask": {
Type: schema.TypeInt,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: rulesSchemaMake(),
},
},
}
}
func natSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"_ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: configSchrmaMake(),
},
},
"devices": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: devicesSchemaMake(),
},
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"nat_id": {
Type: schema.TypeInt,
Computed: true,
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"owner_id": {
Type: schema.TypeInt,
Computed: true,
},
"owner_type": {
Type: schema.TypeString,
Computed: true,
},
"pure_virtual": {
Type: schema.TypeBool,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
}
}
func vnfsSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"dhcp": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: dhcpSchemaMake(),
},
},
"gw": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: gwSchemaMake(),
},
},
"nat": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: natSchemaMake(),
},
},
}
}
func dataSourceVinsSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"vins_id": {
Type: schema.TypeInt,
Required: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
"vnf_dev": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfDevSchemaMake(),
},
},
"_ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the account, which this ViNS belongs to.",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account, which this ViNS belongs to.",
},
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vinsComputeSchemaMake(),
},
},
"default_gw": {
Type: schema.TypeString,
Computed: true,
},
"default_qos": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: qosSchemaMake(),
},
},
"desc": {
Type: schema.TypeString,
Computed: true,
Description: "User-defined text description of this ViNS.",
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"manager_id": {
Type: schema.TypeInt,
Computed: true,
},
"manager_type": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"net_mask": {
Type: schema.TypeInt,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"pre_reservations_num": {
Type: schema.TypeInt,
Computed: true,
},
"redundant": {
Type: schema.TypeBool,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the resource group, where this ViNS is belongs to (for ViNS created at resource group level, 0 otherwise).",
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"sec_vnf_dev_id": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"user_managed": {
Type: schema.TypeBool,
Computed: true,
},
"vnfs": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: vnfsSchemaMake(),
},
},
"vxlan_id": {
Type: schema.TypeInt,
Computed: true,
},
}
return rets
}
func DataSourceVins() *schema.Resource {
@@ -119,63 +904,6 @@ func DataSourceVins() *schema.Resource {
Default: &constants.Timeout60s,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the ViNS. Names are case sensitive and unique within the context of an account or resource group.",
},
/*
"vins_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
*/
"rg_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the resource group, where this ViNS is belongs to (for ViNS created at resource group level, 0 otherwise).",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the account, which this ViNS belongs to.",
},
// the rest of attributes are computed
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account, which this ViNS belongs to.",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "User-defined text description of this ViNS.",
},
"ext_ip_addr": {
Type: schema.TypeString,
Computed: true,
Description: "IP address of the external connection (valid for ViNS connected to external network, empty string otherwise).",
},
"ext_net_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the external network this ViNS is connected to (-1 means no external connection).",
},
"ipcidr": {
Type: schema.TypeString,
Computed: true,
Description: "Network address used by this ViNS.",
},
},
Schema: dataSourceVinsSchemaMake(),
}
}

View File

@@ -0,0 +1,106 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsAuditsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
audits, err := utilityVinsAuditsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsAudits(audits))
return nil
}
func DataSourceVinsAuditsSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"vins_id": {
Type: schema.TypeInt,
Required: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"call": {
Type: schema.TypeString,
Computed: true,
},
"response_time": {
Type: schema.TypeFloat,
Computed: true,
},
"statuscode": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeFloat,
Computed: true,
},
"user": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
return rets
}
func DataSourceVinsAudits() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsAuditsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: DataSourceVinsAuditsSchemaMake(),
}
}

View File

@@ -0,0 +1,110 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsExtNetListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
extNetList, err := utilityVinsExtNetListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsExtNetList(extNetList))
return nil
}
func DataSourceVinsExtNetListchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"vins_id": {
Type: schema.TypeInt,
Required: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"default_gw": {
Type: schema.TypeString,
Computed: true,
},
"ext_net_id": {
Type: schema.TypeInt,
Computed: true,
},
"ip": {
Type: schema.TypeString,
Computed: true,
},
"prefix_len": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
return rets
}
func DataSourceVinsExtNetList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsExtNetListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: DataSourceVinsExtNetListchemaMake(),
}
}

View File

@@ -0,0 +1,114 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsIpListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
ips, err := utilityVinsIpListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsIpList(ips))
return nil
}
func DataSourceVinsIpListSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"vins_id": {
Type: schema.TypeInt,
Required: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"client_type": {
Type: schema.TypeString,
Computed: true,
},
"domainname": {
Type: schema.TypeString,
Computed: true,
},
"hostname": {
Type: schema.TypeString,
Computed: true,
},
"ip": {
Type: schema.TypeString,
Computed: true,
},
"mac": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return rets
}
func DataSourceVinsIpList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsIpListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: DataSourceVinsIpListSchemaMake(),
}
}

View File

@@ -1,190 +1,164 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func flattenVinsList(vl VinsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, v := range vl {
temp := map[string]interface{}{
"account_id": v.AccountId,
"account_name": v.AccountName,
"created_by": v.CreatedBy,
"created_time": v.CreatedTime,
"deleted_by": v.DeletedBy,
"deleted_time": v.DeletedTime,
"external_ip": v.ExternalIP,
"vins_id": v.ID,
"vins_name": v.Name,
"network": v.Network,
"rg_id": v.RGID,
"rg_name": v.RGName,
"status": v.Status,
"updated_by": v.UpdatedBy,
"updated_time": v.UpdatedTime,
"vxlan_id": v.VXLanID,
}
res = append(res, temp)
}
return res
}
func dataSourceVinsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsList, err := utilityVinsListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsList(vinsList))
return nil
}
func dataSourceVinsListSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"include_deleted": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "include deleted computes",
},
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "Page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "Page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"external_ip": {
Type: schema.TypeString,
Computed: true,
},
"vins_id": {
Type: schema.TypeInt,
Computed: true,
},
"vins_name": {
Type: schema.TypeString,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vxlan_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceVinsList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceVinsListSchemaMake(),
}
}
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsList, err := utilityVinsListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsList(vinsList))
return nil
}
func dataSourceVinsListSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"include_deleted": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "include deleted computes",
},
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "Page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "Page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"external_ip": {
Type: schema.TypeString,
Computed: true,
},
"vins_id": {
Type: schema.TypeInt,
Computed: true,
},
"vins_name": {
Type: schema.TypeString,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vxlan_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceVinsList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceVinsListSchemaMake(),
}
}

View File

@@ -0,0 +1,158 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsListDeletedRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsList, err := utilityVinsListDeletedCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsList(vinsList))
return nil
}
func dataSourceVinsListDeletedSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "Page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "Page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"external_ip": {
Type: schema.TypeString,
Computed: true,
},
"vins_id": {
Type: schema.TypeInt,
Computed: true,
},
"vins_name": {
Type: schema.TypeString,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vxlan_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceVinsListDeleted() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsListDeletedRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceVinsListDeletedSchemaMake(),
}
}

View File

@@ -0,0 +1,118 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceVinsNatRuleListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
natRules, err := utilityVinsNatRuleListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenVinsNatRuleList(natRules))
return nil
}
func DataSourceVinsNatRuleListSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"vins_id": {
Type: schema.TypeInt,
Required: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeInt,
Computed: true,
},
"local_ip": {
Type: schema.TypeString,
Computed: true,
},
"local_port": {
Type: schema.TypeInt,
Computed: true,
},
"protocol": {
Type: schema.TypeString,
Computed: true,
},
"public_port_end": {
Type: schema.TypeInt,
Computed: true,
},
"public_port_start": {
Type: schema.TypeInt,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
return rets
}
func DataSourceVinsNatRuleList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsNatRuleListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: DataSourceVinsNatRuleListSchemaMake(),
}
}

View File

@@ -0,0 +1,514 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
func flattenMGMT(mgmt *VNFConfigMGMT) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"ip_addr": mgmt.IPAddr,
"password": mgmt.Password,
"ssh_key": mgmt.SSHKey,
"user": mgmt.User,
}
res = append(res, temp)
return res
}
func flattenResources(resources *VNFConfigResources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": resources.CPU,
"ram": resources.RAM,
"stack_id": resources.StackID,
"uuid": resources.UUID,
}
res = append(res, temp)
return res
}
func flattenConfig(config VNFConfig) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"mgmt": flattenMGMT(&config.MGMT),
"resources": flattenResources(&config.Resources),
}
res = append(res, temp)
return res
}
func flattenQOS(qos QOS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"e_rate": qos.ERate,
"guid": qos.GUID,
"in_brust": qos.InBurst,
"in_rate": qos.InRate,
}
res = append(res, temp)
return res
}
func flattenInterfaces(interfaces VNFInterfaceList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, vnfInterface := range interfaces {
temp := map[string]interface{}{
"conn_id": vnfInterface.ConnID,
"conn_type": vnfInterface.ConnType,
"def_gw": vnfInterface.DefGW,
"flipgroup_id": vnfInterface.FlipGroupID,
"guid": vnfInterface.GUID,
"ip_address": vnfInterface.IPAddress,
"listen_ssh": vnfInterface.ListenSSH,
"mac": vnfInterface.MAC,
"name": vnfInterface.Name,
"net_id": vnfInterface.NetID,
"net_mask": vnfInterface.NetMask,
"net_type": vnfInterface.NetType,
"pci_slot": vnfInterface.PCISlot,
"qos": flattenQOS(vnfInterface.QOS),
"target": vnfInterface.Target,
"type": vnfInterface.Type,
"vnfs": vnfInterface.VNFS,
}
res = append(res, temp)
}
return res
}
func flattenVNFDev(vnfDev VNFDev) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"_ckey": vnfDev.CKey,
"account_id": vnfDev.AccountID,
"capabilities": vnfDev.Capabilities,
"config": flattenConfig(vnfDev.Config), //in progress
"config_saved": vnfDev.ConfigSaved,
"custom_pre_cfg": vnfDev.CustomPreConfig,
"desc": vnfDev.Description,
"gid": vnfDev.GID,
"guid": vnfDev.GUID,
"vnf_id": vnfDev.ID,
"interfaces": flattenInterfaces(vnfDev.Interfaces),
"lock_status": vnfDev.LockStatus,
"milestones": vnfDev.Milestones,
"vnf_name": vnfDev.Name,
"status": vnfDev.Status,
"tech_status": vnfDev.TechStatus,
"type": vnfDev.Type,
"vins": vnfDev.VINS,
}
res = append(res, temp)
return res
}
func flattenComputes(computes VINSComputeList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, compute := range computes {
temp := map[string]interface{}{
"compute_id": compute.ID,
"compute_name": compute.Name,
}
res = append(res, temp)
}
return res
}
func flattenReservations(reservations ReservationList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, reservation := range reservations {
temp := map[string]interface{}{
"client_type": reservation.ClientType,
"desc": reservation.Description,
"domainname": reservation.DomainName,
"hostname": reservation.HostName,
"ip": reservation.IP,
"mac": reservation.MAC,
"type": reservation.Type,
"vm_id": reservation.VMID,
}
res = append(res, temp)
}
return res
}
func flattenDHCPConfig(config DHCPConfig) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"default_gw": config.DefaultGW,
"dns": config.DNS,
"ip_end": config.IPEnd,
"ip_start": config.IPStart,
"lease": config.Lease,
"netmask": config.Netmask,
"network": config.Network,
"reservations": flattenReservations(config.Reservations),
}
res = append(res, temp)
return res
}
func flattenPrimary(primary DevicePrimary) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"dev_id": primary.DevID,
"iface01": primary.IFace01,
"iface02": primary.IFace02,
}
res = append(res, temp)
return res
}
func flattenDevices(devices Devices) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"primary": flattenPrimary(devices.Primary),
}
res = append(res, temp)
return res
}
func flattenDHCP(dhcp DHCP) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"_ckey": dhcp.CKey,
"account_id": dhcp.AccountID,
"config": flattenDHCPConfig(dhcp.Config),
"created_time": dhcp.CreatedTime,
"devices": flattenDevices(dhcp.Devices),
"gid": dhcp.GID,
"guid": dhcp.GUID,
"dhcp_id": dhcp.ID,
"lock_status": dhcp.LockStatus,
"milestones": dhcp.Milestones,
"owner_id": dhcp.OwnerID,
"owner_type": dhcp.OwnerType,
"pure_virtual": dhcp.PureVirtual,
"status": dhcp.Status,
"tech_status": dhcp.TechStatus,
"type": dhcp.Type,
}
res = append(res, temp)
return res
}
func flattenGWConfig(config GWConfig) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"default_gw": config.DefaultGW,
"ext_net_id": config.ExtNetID,
"ext_net_ip": config.ExtNetIP,
"ext_netmask": config.ExtNetMask,
"qos": flattenQOS(config.QOS),
}
res = append(res, temp)
return res
}
func flattenGW(gw GW) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"_ckey": gw.CKey,
"account_id": gw.AccountID,
"config": flattenGWConfig(gw.Config),
"created_time": gw.CreatedTime,
"devices": flattenDevices(gw.Devices),
"gid": gw.GID,
"guid": gw.GUID,
"gw_id": gw.ID,
"lock_status": gw.LockStatus,
"milestones": gw.Milestones,
"owner_id": gw.OwnerID,
"owner_type": gw.OwnerType,
"pure_virtual": gw.PureVirtual,
"status": gw.Status,
"tech_status": gw.TechStatus,
"type": gw.Type,
}
res = append(res, temp)
return res
}
func flattenRules(rules ListNATRules) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rule := range rules {
tmp := map[string]interface{}{
"rule_id": rule.ID,
"local_ip": rule.LocalIP,
"local_port": rule.LocalPort,
"protocol": rule.Protocol,
"public_port_end": rule.PublicPortEnd,
"public_port_start": rule.PublicPortStart,
"vm_id": rule.VMID,
"vm_name": rule.VMName,
}
res = append(res, tmp)
}
return res
}
func flattenNATConfig(config NATConfig) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"net_mask": config.NetMask,
"network": config.Network,
"rules": flattenRules(config.Rules),
}
res = append(res, temp)
return res
}
func flattenNAT(nat NAT) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"_ckey": nat.CKey,
"account_id": nat.AccountID,
"created_time": nat.CreatedTime,
"config": flattenNATConfig(nat.Config),
"devices": flattenDevices(nat.Devices),
"gid": nat.GID,
"guid": nat.GUID,
"nat_id": nat.ID,
"lock_status": nat.LockStatus,
"milestones": nat.Milestones,
"owner_id": nat.OwnerID,
"owner_type": nat.OwnerType,
"pure_virtual": nat.PureVirtual,
"status": nat.Status,
"tech_status": nat.TechStatus,
"type": nat.Type,
}
res = append(res, temp)
return res
}
func flattenVNFS(vnfs VNFS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"dhcp": flattenDHCP(vnfs.DHCP),
"gw": flattenGW(vnfs.GW),
"nat": flattenNAT(vnfs.NAT),
}
res = append(res, temp)
return res
}
func flattenRuleBlock(rules ListNATRules) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rule := range rules {
tmp := map[string]interface{}{
"int_ip": rule.LocalIP,
"int_port": rule.LocalPort,
"ext_port_start": rule.PublicPortStart,
"ext_port_end": rule.PublicPortEnd,
"proto": rule.Protocol,
"rule_id": rule.ID,
}
res = append(res, tmp)
}
return res
}
func flattenVins(d *schema.ResourceData, vins VINSDetailed) {
d.Set("vins_id", vins.ID)
d.Set("vnf_dev", flattenVNFDev(vins.VNFDev))
d.Set("_ckey", vins.CKey)
d.Set("account_id", vins.AccountID)
d.Set("account_name", vins.AccountName)
d.Set("computes", flattenComputes(vins.Computes))
d.Set("default_gw", vins.DefaultGW)
d.Set("default_qos", flattenQOS(vins.DefaultQOS))
d.Set("desc", vins.Description)
d.Set("gid", vins.GID)
d.Set("guid", vins.GUID)
d.Set("lock_status", vins.LockStatus)
d.Set("manager_id", vins.ManagerID)
d.Set("manager_type", vins.ManagerType)
d.Set("milestones", vins.Milestones)
d.Set("name", vins.Name)
d.Set("net_mask", vins.NetMask)
d.Set("network", vins.Network)
d.Set("pre_reservations_num", vins.PreReservaionsNum)
d.Set("redundant", vins.Redundant)
d.Set("rg_id", vins.RGID)
d.Set("rg_name", vins.RGName)
d.Set("sec_vnf_dev_id", vins.SecVNFDevID)
d.Set("status", vins.Status)
d.Set("user_managed", vins.UserManaged)
d.Set("vnfs", flattenVNFS(vins.VNFS))
d.Set("vxlan_id", vins.VXLanID)
d.Set("nat_rule", flattenRuleBlock(vins.VNFS.NAT.Config.Rules))
}
func flattenVinsData(d *schema.ResourceData, vins VINSDetailed) {
d.Set("vins_id", vins.ID)
d.Set("vnf_dev", flattenVNFDev(vins.VNFDev))
d.Set("_ckey", vins.CKey)
d.Set("account_id", vins.AccountID)
d.Set("account_name", vins.AccountName)
d.Set("computes", flattenComputes(vins.Computes))
d.Set("default_gw", vins.DefaultGW)
d.Set("default_qos", flattenQOS(vins.DefaultQOS))
d.Set("desc", vins.Description)
d.Set("gid", vins.GID)
d.Set("guid", vins.GUID)
d.Set("lock_status", vins.LockStatus)
d.Set("manager_id", vins.ManagerID)
d.Set("manager_type", vins.ManagerType)
d.Set("milestones", vins.Milestones)
d.Set("name", vins.Name)
d.Set("net_mask", vins.NetMask)
d.Set("network", vins.Network)
d.Set("pre_reservations_num", vins.PreReservaionsNum)
d.Set("redundant", vins.Redundant)
d.Set("rg_id", vins.RGID)
d.Set("rg_name", vins.RGName)
d.Set("sec_vnf_dev_id", vins.SecVNFDevID)
d.Set("status", vins.Status)
d.Set("user_managed", vins.UserManaged)
d.Set("vnfs", flattenVNFS(vins.VNFS))
d.Set("vxlan_id", vins.VXLanID)
}
func flattenVinsAudits(auidts VINSAuditsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, audit := range auidts {
temp := map[string]interface{}{
"call": audit.Call,
"response_time": audit.ResponseTime,
"statuscode": audit.StatusCode,
"timestamp": audit.Timestamp,
"user": audit.User,
}
res = append(res, temp)
}
return res
}
func flattenVinsExtNetList(extNetList ExtNetList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, extNet := range extNetList {
temp := map[string]interface{}{
"default_gw": extNet.DefaultGW,
"ext_net_id": extNet.ExtNetID,
"ip": extNet.IP,
"prefix_len": extNet.PrefixLen,
"status": extNet.Status,
"tech_status": extNet.TechStatus,
}
res = append(res, temp)
}
return res
}
func flattenVinsIpList(ips IPList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, ip := range ips {
temp := map[string]interface{}{
"client_type": ip.ClientType,
"domainname": ip.DomainName,
"hostname": ip.HostName,
"ip": ip.IP,
"mac": ip.MAC,
"type": ip.Type,
"vm_id": ip.VMID,
}
res = append(res, temp)
}
return res
}
func flattenVinsList(vl VINSList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, v := range vl {
temp := map[string]interface{}{
"account_id": v.AccountID,
"account_name": v.AccountName,
"created_by": v.CreatedBy,
"created_time": v.CreatedTime,
"deleted_by": v.DeletedBy,
"deleted_time": v.DeletedTime,
"external_ip": v.ExternalIP,
"vins_id": v.ID,
"vins_name": v.Name,
"network": v.Network,
"rg_id": v.RGID,
"rg_name": v.RGName,
"status": v.Status,
"updated_by": v.UpdatedBy,
"updated_time": v.UpdatedTime,
"vxlan_id": v.VXLANID,
}
res = append(res, temp)
}
return res
}
func flattenVinsNatRuleList(natRules NATRuleList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, natRule := range natRules {
temp := map[string]interface{}{
"id": natRule.ID,
"local_ip": natRule.LocalIP,
"local_port": natRule.LocalPort,
"protocol": natRule.Protocol,
"public_port_end": natRule.PublicPortEnd,
"public_port_start": natRule.PublicPortStart,
"vm_id": natRule.VMID,
"vm_name": natRule.VMName,
}
res = append(res, temp)
}
return res
}

View File

@@ -1,94 +1,330 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
type Vins struct {
AccountId int `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime int `json:"createdTime"`
DeletedBy string `json:"deletedBy"`
DeletedTime int `json:"deletedTime"`
ExternalIP string `json:"externalIP"`
ID int `json:"id"`
Name string `json:"name"`
Network string `json:"network"`
RGID int `json:"rgId"`
RGName string `json:"rgName"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime int `json:"updatedTime"`
VXLanID int `json:"vxlanId"`
}
type VinsList []Vins
type VinsSearchResp []VinsSearchRecord
type VnfRecord struct {
ID int `json:"id"`
AccountID int `json:"accountId"`
Type string `json:"type"` // "DHCP", "NAT", "GW" etc
Config map[string]interface{} `json:"config"` // NOTE: VNF specs vary by VNF type
}
type VnfGwConfigRecord struct { // describes GW VNF config structure inside ViNS, as returned by API vins/get
ExtNetID int `json:"ext_net_id"`
ExtNetIP string `json:"ext_net_ip"`
ExtNetMask int `json:"ext_net_mask"`
DefaultGW string `json:"default_gw"`
}
type VinsRecord struct { // represents part of the response from API vins/get
ID int `json:"id"`
Name string `json:"name"`
IPCidr string `json:"network"`
VxLanID int `json:"vxlanId"`
ExternalIP string `json:"externalIP"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
RgID int `json:"rgid"`
RgName string `json:"rgName"`
VNFs map[string]VnfRecord `json:"vnfs"`
Desc string `json:"desc"`
}
type VinsSearchRecord struct {
ID int `json:"id"`
Name string `json:"name"`
IPCidr string `json:"network"`
VxLanID int `json:"vxlanId"`
ExternalIP string `json:"externalIP"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
}
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
type VINSRecord struct {
AccountID uint64 `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"`
DeletedTime uint64 `json:"deletedTime"`
ExternalIP string `json:"externalIP"`
ID uint64 `json:"id"`
Name string `json:"name"`
Network string `json:"network"`
RGID uint64 `json:"rgId"`
RGName string `json:"rgName"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"`
VXLANID uint64 `json:"vxlanId"`
}
type VINSList []VINSRecord
type VINSAudits struct {
Call string `json:"call"`
ResponseTime float64 `json:"responsetime"`
StatusCode uint64 `json:"statuscode"`
Timestamp float64 `json:"timestamp"`
User string `json:"user"`
}
type VINSAuditsList []VINSAudits
type VINSExtNet struct {
DefaultGW string `json:"default_gw"`
ExtNetID uint64 `json:"ext_net_id"`
IP string `json:"ip"`
PrefixLen uint64 `json:"prefixlen"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
}
type ExtNetList []VINSExtNet
type IP struct {
ClientType string `json:"clientType"`
DomainName string `json:"domainname"`
HostName string `json:"hostname"`
IP string `json:"ip"`
MAC string `json:"mac"`
Type string `json:"type"`
VMID uint64 `json:"vmId"`
}
type IPList []IP
type VNFDev struct {
CKey string `json:"_ckey"`
AccountID uint64 `json:"accountId"`
Capabilities []string `json:"capabilities"`
Config VNFConfig `json:"config"`
ConfigSaved bool `json:"configSaved"`
CustomPreConfig bool `json:"customPrecfg"`
Description string `json:"desc"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"`
Interfaces VNFInterfaceList `json:"interfaces"`
LockStatus string `json:"lockStatus"`
Milestones uint64 `json:"milestones"`
Name string `json:"name"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
VINS []uint64 `json:"vins"`
}
type VNFConfig struct {
MGMT VNFConfigMGMT `json:"mgmt"`
Resources VNFConfigResources `json:"resources"`
}
type VNFConfigMGMT struct {
IPAddr string `json:"ipaddr"`
Password string `json:"password"`
SSHKey string `json:"sshkey"`
User string `json:"user"`
}
type VNFConfigResources struct {
CPU uint64 `json:"cpu"`
RAM uint64 `json:"ram"`
StackID uint64 `json:"stackId"`
UUID string `json:"uuid"`
}
type VNFInterface struct {
ConnID uint64 `json:"connId"`
ConnType string `json:"connType"`
DefGW string `json:"defGw"`
FlipGroupID uint64 `json:"flipgroupId"`
GUID string `json:"guid"`
IPAddress string `json:"ipAddress"`
ListenSSH bool `json:"listenSsh"`
MAC string `json:"mac"`
Name string `json:"name"`
NetID uint64 `json:"netId"`
NetMask uint64 `json:"netMask"`
NetType string `json:"netType"`
PCISlot uint64 `json:"pciSlot"`
QOS QOS `json:"qos"`
Target string `json:"target"`
Type string `json:"type"`
VNFS []uint64 `json:"vnfs"`
}
type QOS struct {
ERate uint64 `json:"eRate"`
GUID string `json:"guid"`
InBurst uint64 `json:"inBurst"`
InRate uint64 `json:"inRate"`
}
type VNFInterfaceList []VNFInterface
type VINSCompute struct {
ID uint64 `json:"id"`
Name string `json:"name"`
}
type VINSComputeList []VINSCompute
type VNFS struct {
DHCP DHCP `json:"DHCP"`
GW GW `json:"GW"`
NAT NAT `json:"NAT"`
}
type NAT struct {
CKey string `json:"_ckey"`
AccountID uint64 `json:"accountId"`
CreatedTime uint64 `json:"createdTime"`
Config NATConfig `json:"config"`
Devices Devices `json:"devices"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"`
LockStatus string `json:"lockStatus"`
Milestones uint64 `json:"milestones"`
OwnerID uint64 `json:"ownerId"`
OwnerType string `json:"ownerType"`
PureVirtual bool `json:"pureVirtual"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
}
type NATConfig struct {
NetMask uint64 `json:"netmask"`
Network string `json:"network"`
Rules ListNATRules `json:"rules"`
}
type ItemNATRule struct {
ID uint64 `json:"id"`
LocalIP string `json:"localIp"`
LocalPort uint64 `json:"localPort"`
Protocol string `json:"protocol"`
PublicPortEnd uint64 `json:"publicPortEnd"`
PublicPortStart uint64 `json:"publicPortStart"`
VMID uint64 `json:"vmId"`
VMName string `json:"vmName"`
}
type ListNATRules []ItemNATRule
type GW struct {
CKey string `json:"_ckey"`
AccountID uint64 `json:"accountId"`
Config GWConfig `json:"config"`
CreatedTime uint64 `json:"createdTime"`
Devices Devices `json:"devices"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"`
LockStatus string `json:"lockStatus"`
Milestones uint64 `json:"milestones"`
OwnerID uint64 `json:"ownerId"`
OwnerType string `json:"ownerType"`
PureVirtual bool `json:"pureVirtual"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
}
type GWConfig struct {
DefaultGW string `json:"default_gw"`
ExtNetID uint64 `json:"ext_net_id"`
ExtNetIP string `json:"ext_net_ip"`
ExtNetMask uint64 `json:"ext_netmask"`
QOS QOS `json:"qos"`
}
type Devices struct {
Primary DevicePrimary `json:"primary"`
}
type DevicePrimary struct {
DevID uint64 `json:"devId"`
IFace01 string `json:"iface01"`
IFace02 string `json:"iface02"`
}
type DHCP struct {
CKey string `json:"_ckey"`
AccountID uint64 `json:"accountId"`
Config DHCPConfig `json:"config"`
CreatedTime uint64 `json:"createdTime"`
Devices Devices `json:"devices"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"`
LockStatus string `json:"lockStatus"`
Milestones uint64 `json:"milestones"`
OwnerID uint64 `json:"ownerId"`
OwnerType string `json:"ownerType"`
PureVirtual bool `json:"pureVirtual"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
}
type DHCPConfig struct {
DefaultGW string `json:"default_gw"`
DNS []string `json:"dns"`
IPEnd string `json:"ip_end"`
IPStart string `json:"ip_start"`
Lease uint64 `json:"lease"`
Netmask uint64 `json:"netmask"`
Network string `json:"network"`
Reservations ReservationList `json:"reservations"`
}
type VINSDetailed struct {
VNFDev VNFDev `json:"VNFDev"`
CKey string `json:"_ckey"`
AccountID uint64 `json:"accountId"`
AccountName string `json:"accountName"`
Computes VINSComputeList `json:"computes"`
DefaultGW string `json:"defaultGW"`
DefaultQOS QOS `json:"defaultQos"`
Description string `json:"desc"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"`
LockStatus string `json:"lockStatus"`
ManagerID uint64 `json:"managerId"`
ManagerType string `json:"managerType"`
Milestones uint64 `json:"milestones"`
Name string `json:"name"`
NetMask uint64 `json:"netMask"`
Network string `json:"network"`
PreReservaionsNum uint64 `json:"preReservationsNum"`
Redundant bool `json:"redundant"`
RGID uint64 `json:"rgId"`
RGName string `json:"rgName"`
SecVNFDevID uint64 `json:"secVnfDevId"`
Status string `json:"status"`
UserManaged bool `json:"userManaged"`
VNFS VNFS `json:"vnfs"`
VXLanID uint64 `json:"vxlanId"`
}
type Reservation struct {
ClientType string `json:"clientType"`
Description string `json:"desc"`
DomainName string `json:"domainname"`
HostName string `json:"hostname"`
IP string `json:"ip"`
MAC string `json:"mac"`
Type string `json:"type"`
VMID int `json:"vmId"`
}
type ReservationList []Reservation
type NATRule struct {
ID uint64 `json:"id"`
LocalIP string `json:"localIp"`
LocalPort uint64 `json:"localPort"`
Protocol string `json:"protocol"`
PublicPortEnd uint64 `json:"publicPortEnd"`
PublicPortStart uint64 `json:"publicPortStart"`
VMID uint64 `json:"vmId"`
VMName string `json:"vmName"`
}
type NATRuleList []NATRule

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -39,6 +40,8 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/dc"
"github.com/rudecs/terraform-provider-decort/internal/status"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -46,112 +49,221 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func ipcidrDiffSupperss(key, oldVal, newVal string, d *schema.ResourceData) bool {
if oldVal == "" && newVal != "" {
// if old value for "ipcidr" resource is empty string, it means that we are creating new ViNS
// and there is a chance that the user will want specific IP address range for this ViNS -
// check if "ipcidr" is explicitly set in TF file to a non-empty string.
log.Debugf("ipcidrDiffSupperss: key=%s, oldVal=%q, newVal=%q -> suppress=FALSE", key, oldVal, newVal)
return false // there is a difference between stored and new value
}
log.Debugf("ipcidrDiffSupperss: key=%s, oldVal=%q, newVal=%q -> suppress=TRUE", key, oldVal, newVal)
return true // suppress difference
}
func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceVinsCreate: called for ViNS name %s, Account ID %d, RG ID %d",
d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
apiToCall := VinsCreateInAccountAPI
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
argVal, argSet := d.GetOk("rg_id")
if argSet && argVal.(int) > 0 {
apiToCall = VinsCreateInRgAPI
urlValues.Add("rgId", fmt.Sprintf("%d", argVal.(int)))
} else {
// RG ID either not set at all or set to 0 - user may want ViNS at account level
argVal, argSet = d.GetOk("account_id")
if !argSet || argVal.(int) <= 0 {
// No valid Account ID (and no RG ID either) - cannot create ViNS
return diag.Errorf("resourceVinsCreate: ViNS name %s - no valid account and/or resource group ID specified", d.Id())
}
urlValues.Add("accountId", fmt.Sprintf("%d", argVal.(int)))
rgId, rgOk := d.GetOk("rg_id")
accountId, accountIdOk := d.GetOk("account_id")
if !rgOk && !accountIdOk {
return diag.Errorf("resourceVinsCreate: no valid accountId or resource group ID specified")
}
argVal, argSet = d.GetOk("ext_net_id") // NB: even if ext_net_id value is explicitly set to 0, argSet = false anyway
if argSet {
if argVal.(int) > 0 {
// connect to specific external network
urlValues.Add("extNetId", fmt.Sprintf("%d", argVal.(int)))
/*
Commented out, as we've made "ext_net_ip" parameter non-configurable via Terraform!
if rgOk {
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("rgId", strconv.Itoa(rgId.(int)))
if ipcidr, ok := d.GetOk("ipcidr"); ok {
urlValues.Add("ipcidr", ipcidr.(string))
}
// in case of specific ext net connection user may also want a particular IP address
argVal, argSet = d.GetOk("ext_net_ip")
if argSet && argVal.(string) != "" {
urlValues.Add("extIp", argVal.(string))
//extnet v1
urlValues.Add("extNetId", strconv.Itoa(d.Get("ext_net_id").(int)))
if extIp, ok := d.GetOk("ext_ip_addr"); ok {
urlValues.Add("extIp", extIp.(string))
}
//extnet v2
if extNetResp, ok := d.GetOk("ext_net"); ok {
extNetSl := extNetResp.([]interface{})
extNet := extNetSl[0].(map[string]interface{})
urlValues.Add("vinsId", d.Id())
urlValues.Add("netId", strconv.Itoa(extNet["ext_net_id"].(int)))
urlValues.Add("extIp", extNet["ext_net_ip"].(string))
}
if desc, ok := d.GetOk("desc"); ok {
urlValues.Add("desc", desc.(string))
}
urlValues.Add("preReservationsNum", strconv.Itoa(d.Get("pre_reservations_num").(int)))
id, err := c.DecortAPICall(ctx, "POST", VinsCreateInRgAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
d.SetId(id)
} else if accountIdOk {
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
if gid, ok := d.GetOk("gid"); ok {
urlValues.Add("gid", strconv.Itoa(gid.(int)))
}
if ipcidr, ok := d.GetOk("ipcidr"); ok {
urlValues.Add("ipcidr", ipcidr.(string))
}
if desc, ok := d.GetOk("desc"); ok {
urlValues.Add("desc", desc.(string))
}
urlValues.Add("preReservationsNum", strconv.Itoa(d.Get("pre_reservations_num").(int)))
id, err := c.DecortAPICall(ctx, "POST", VinsCreateInAccountAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
d.SetId(id)
}
warnings := dc.Warnings{}
urlValues = &url.Values{}
if ipRes, ok := d.GetOk("ip"); ok {
ipsSlice := ipRes.([]interface{})
for _, ipInterfase := range ipsSlice {
ip := ipInterfase.(map[string]interface{})
urlValues = &url.Values{}
urlValues.Add("vinsId", d.Id())
urlValues.Add("type", ip["type"].(string))
if ipAddr, ok := ip["ip_addr"]; ok {
urlValues.Add("ipAddr", ipAddr.(string))
}
if macAddr, ok := ip["mac_addr"]; ok {
urlValues.Add("mac", macAddr.(string))
}
if computeId, ok := ip["compute_id"]; ok {
urlValues.Add("computeId", strconv.Itoa(computeId.(int)))
}
_, err := c.DecortAPICall(ctx, "POST", VinsIpReserveAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
}
urlValues = &url.Values{}
if natRule, ok := d.GetOk("nat_rule"); ok {
addedNatRules := natRule.([]interface{})
if len(addedNatRules) > 0 {
for _, natRuleInterface := range addedNatRules {
urlValues = &url.Values{}
natRule := natRuleInterface.(map[string]interface{})
urlValues.Add("vinsId", d.Id())
urlValues.Add("intIp", natRule["int_ip"].(string))
urlValues.Add("intPort", strconv.Itoa(natRule["int_port"].(int)))
urlValues.Add("extPortStart", strconv.Itoa(natRule["ext_port_start"].(int)))
urlValues.Add("extPortEnd", strconv.Itoa(natRule["ext_port_end"].(int)))
urlValues.Add("proto", natRule["proto"].(string))
_, err := c.DecortAPICall(ctx, "POST", VinsNatRuleAddAPI, urlValues)
if err != nil {
warnings.Add(err)
}
*/
} else {
// ext_net_id is set to a negative value - connect to default external network
// no particular IP address selection in this case
urlValues.Add("extNetId", "0")
}
}
}
argVal, argSet = d.GetOk("ipcidr")
if argSet && argVal.(string) != "" {
log.Debugf("resourceVinsCreate: ipcidr is set to %s", argVal.(string))
urlValues.Add("ipcidr", argVal.(string))
}
argVal, argSet = d.GetOk("description")
if argSet {
urlValues.Add("desc", argVal.(string))
}
apiResp, err := c.DecortAPICall(ctx, "POST", apiToCall, urlValues)
if err != nil {
return diag.FromErr(err)
}
d.SetId(apiResp) // update ID of the resource to tell Terraform that the ViNS resource exists
vinsId, _ := strconv.Atoi(apiResp)
log.Debugf("resourceVinsCreate: new ViNS ID / name %d / %s creation sequence complete", vinsId, d.Get("name").(string))
// We may reuse dataSourceVinsRead here as we maintain similarity
// between ViNS resource and ViNS data source schemas
// ViNS resource read function will also update resource ID on success, so that Terraform
// will know the resource exists (however, we already did it a few lines before)
return dataSourceVinsRead(ctx, d, m)
defer resourceVinsRead(ctx, d, m)
return warnings.Get()
}
func resourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
// if empty string is returned from utilityVinsCheckPresence then there is no
// such ViNS and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
warnings := dc.Warnings{}
vins, err := utilityVinsCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
return flattenVins(d, vinsFacts)
hasChangeState := false
if vins.Status == status.Destroyed {
d.SetId("")
d.Set("vins_id", 0)
return resourceVinsCreate(ctx, d, m)
} else if vins.Status == status.Deleted {
hasChangeState = true
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsRestoreAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
urlValues = &url.Values{}
isEnabled := d.Get("enable").(bool)
if vins.Status == status.Disabled && isEnabled {
hasChangeState = true
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsEnableAPI, urlValues)
if err != nil {
warnings.Add(err)
}
} else if vins.Status == status.Enabled && !isEnabled {
hasChangeState = true
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsDisableAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
if hasChangeState {
vins, err = utilityVinsCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
}
flattenVins(d, *vins)
return warnings.Get()
}
func isContainsIp(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})
elConv := el.(map[string]interface{})
if elOldConv["ip_addr"].(string) == elConv["ip_addr"].(string) {
return true
}
}
return false
}
func isContinsNatRule(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})
elConv := el.(map[string]interface{})
if elOldConv["int_ip"].(string) == elConv["int_ip"].(string) &&
elOldConv["int_port"].(int) == elConv["int_port"].(int) &&
elOldConv["ext_port_start"].(int) == elConv["ext_port_start"].(int) {
return true
}
}
return false
}
func resourceVinsUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceVinsUpdate: called for ViNS ID / name %s / %s, Account ID %d, RG ID %d",
d.Id(), d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
warnings := dc.Warnings{}
// 1. Handle external network connection change
enableOld, enableNew := d.GetChange("enable")
if enableOld.(bool) && !enableNew.(bool) {
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsDisableAPI, urlValues)
if err != nil {
warnings.Add(err)
}
} else if !enableOld.(bool) && enableNew.(bool) {
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsEnableAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
//extnet v1
oldExtNetId, newExtNedId := d.GetChange("ext_net_id")
if oldExtNetId.(int) != newExtNedId.(int) {
log.Debugf("resourceVinsUpdate: changing ViNS ID %s - ext_net_id %d -> %d", d.Id(), oldExtNetId.(int), newExtNedId.(int))
@@ -163,46 +275,178 @@ func resourceVinsUpdate(ctx context.Context, d *schema.ResourceData, m interface
// there was preexisting external net connection - disconnect ViNS
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetDisconnectAPI, extnetParams)
if err != nil {
return diag.FromErr(err)
warnings.Add(err)
}
}
if newExtNedId.(int) > 0 {
// new external network connection requested - connect ViNS
extnetParams.Add("netId", fmt.Sprintf("%d", newExtNedId.(int)))
extNetIp, ok := d.GetOk("ext_net_ip")
if ok && extNetIp.(string) != "" {
urlValues.Add("Ip", extNetIp.(string))
}
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetConnectAPI, extnetParams)
if err != nil {
return diag.FromErr(err)
warnings.Add(err)
}
}
}
// we may reuse dataSourceVinsRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return dataSourceVinsRead(ctx, d, m)
urlValues = &url.Values{}
if d.HasChange("ip") {
deletedIps := make([]interface{}, 0)
addedIps := make([]interface{}, 0)
oldIpInterface, newIpInterface := d.GetChange("ip")
oldIpSlice := oldIpInterface.([]interface{})
newIpSlice := newIpInterface.([]interface{})
for _, el := range oldIpSlice {
if !isContainsIp(newIpSlice, el) {
deletedIps = append(deletedIps, el)
}
}
for _, el := range newIpSlice {
if !isContainsIp(oldIpSlice, el) {
addedIps = append(addedIps, el)
}
}
if len(deletedIps) > 0 {
for _, ipInterfase := range deletedIps {
urlValues = &url.Values{}
ip := ipInterfase.(map[string]interface{})
urlValues.Add("vinsId", d.Id())
if ip["ip_addr"].(string) != "" {
urlValues.Add("ipAddr", ip["ip_addr"].(string))
}
if ip["mac_addr"].(string) != "" {
urlValues.Add("mac", ip["mac_addr"].(string))
}
_, err := c.DecortAPICall(ctx, "POST", VinsIpReleaseAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
}
if len(addedIps) > 0 {
for _, ipInterfase := range addedIps {
urlValues = &url.Values{}
ip := ipInterfase.(map[string]interface{})
urlValues.Add("vinsId", d.Id())
urlValues.Add("type", ip["type"].(string))
if ip["ip_addr"].(string) != "" {
urlValues.Add("ipAddr", ip["ip_addr"].(string))
}
if ip["mac_addr"].(string) != "" {
urlValues.Add("mac", ip["mac_addr"].(string))
}
if ip["compute_id"].(int) != 0 {
urlValues.Add("computeId", strconv.Itoa(ip["compute_id"].(int)))
}
_, err := c.DecortAPICall(ctx, "POST", VinsIpReserveAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
}
}
if d.HasChange("nat_rule") {
deletedNatRules := make([]interface{}, 0)
addedNatRules := make([]interface{}, 0)
oldNatRulesInterface, newNatRulesInterface := d.GetChange("nat_rule")
oldNatRulesSlice := oldNatRulesInterface.([]interface{})
newNatRulesSlice := newNatRulesInterface.([]interface{})
for _, el := range oldNatRulesSlice {
if !isContinsNatRule(newNatRulesSlice, el) {
deletedNatRules = append(deletedNatRules, el)
}
}
for _, el := range newNatRulesSlice {
if !isContinsNatRule(oldNatRulesSlice, el) {
addedNatRules = append(addedNatRules, el)
}
}
if len(deletedNatRules) > 0 {
for _, natRuleInterface := range deletedNatRules {
urlValues = &url.Values{}
natRule := natRuleInterface.(map[string]interface{})
urlValues.Add("vinsId", d.Id())
urlValues.Add("ruleId", strconv.Itoa(natRule["rule_id"].(int)))
log.Debug("NAT_RULE_DEL_WITH: ", urlValues.Encode())
_, err := c.DecortAPICall(ctx, "POST", VinsNatRuleDelAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
}
if len(addedNatRules) > 0 {
for _, natRuleInterface := range addedNatRules {
urlValues = &url.Values{}
natRule := natRuleInterface.(map[string]interface{})
urlValues.Add("vinsId", d.Id())
urlValues.Add("intIp", natRule["int_ip"].(string))
urlValues.Add("intPort", strconv.Itoa(natRule["int_port"].(int)))
urlValues.Add("extPortStart", strconv.Itoa(natRule["ext_port_start"].(int)))
if natRule["ext_port_end"].(int) != 0 {
urlValues.Add("extPortEnd", strconv.Itoa(natRule["ext_port_end"].(int)))
}
if natRule["proto"].(string) != "" {
urlValues.Add("proto", natRule["proto"].(string))
}
log.Debug("NAT_RULE_ADD_WITH: ", urlValues.Encode())
_, err := c.DecortAPICall(ctx, "POST", VinsNatRuleAddAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
}
}
if oldRestart, newRestart := d.GetChange("vnfdev_restart"); oldRestart == false && newRestart == true {
urlValues = &url.Values{}
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsVnfdevRestartAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
if oldRedeploy, newRedeploy := d.GetChange("vnfdev_redeploy"); oldRedeploy == false && newRedeploy == true {
urlValues = &url.Values{}
urlValues.Add("vinsId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", VinsVnfdevRedeployAPI, urlValues)
if err != nil {
warnings.Add(err)
}
}
defer resourceVinsRead(ctx, d, m)
return warnings.Get()
}
func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceVinsDelete: called for ViNS ID / name %s / %s, Account ID %d, RG ID %d",
d.Id(), d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
if err != nil {
return diag.FromErr(err)
}
// the specified ViNS 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("vinsId", d.Id())
params.Add("force", "1") // disconnect all computes before deleting ViNS
params.Add("permanently", "1") // delete ViNS immediately bypassing recycle bin
urlValues := &url.Values{}
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", VinsDeleteAPI, params)
urlValues.Add("vinsId", d.Id())
urlValues.Add("force", strconv.FormatBool(d.Get("force").(bool)))
urlValues.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
_, err := c.DecortAPICall(ctx, "POST", VinsDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
@@ -210,73 +454,179 @@ func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface
return nil
}
func resourceVinsSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
Description: "Name of the ViNS. Names are case sensitive and unique within the context of an account or resource group.",
},
/* we do not need ViNS ID as an argument because if we already know this ID, it is not practical to call resource provider.
Resource Import will work anyway, as it obtains the ID of ViNS to be imported through another mechanism.
"vins_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
},
*/
"rg_id": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Default: 0,
Description: "ID of the resource group, where this ViNS belongs to. Non-zero for ViNS created at resource group level, 0 otherwise.",
},
"account_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "ID of the account, which this ViNS belongs to. For ViNS created at account level, resource group ID is 0.",
},
func extNetSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"ext_net_id": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(0),
Description: "ID of the external network this ViNS is connected to. Pass 0 if no external connection required.",
Type: schema.TypeInt,
Default: 0,
Optional: true,
},
"ext_net_ip": {
Type: schema.TypeInt,
Optional: true,
Default: "",
},
}
}
"ipcidr": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: ipcidrDiffSupperss,
Description: "Network address to use by this ViNS. This parameter is only valid when creating new ViNS.",
func ipSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
},
"ip_addr": {
Type: schema.TypeString,
Optional: true,
},
"mac_addr": {
Type: schema.TypeString,
Optional: true,
},
"compute_id": {
Type: schema.TypeInt,
Optional: true,
},
}
}
"description": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Optional user-defined text description of this ViNS.",
func natRuleSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"int_ip": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"int_port": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"ext_port_start": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"ext_port_end": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"proto": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"tcp", "udp"}, false),
Computed: true,
},
"rule_id": {
Type: schema.TypeInt,
Computed: true,
},
}
}
// the rest of attributes are computed
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account, which this ViNS belongs to.",
func resourceVinsSchemaMake() map[string]*schema.Schema {
rets := dataSourceVinsSchemaMake()
rets["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
}
rets["rg_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
}
rets["account_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
}
rets["ext_net_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: -1,
}
rets["ext_ip_addr"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "",
}
rets["ipcidr"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
}
rets["pre_reservations_num"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 32,
}
rets["gid"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
}
rets["enable"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
}
rets["permanently"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
}
rets["force"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
}
rets["ext_net"] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: extNetSchemaMake(),
},
}
rets["ip"] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: ipSchemaMake(),
},
}
rets["nat_rule"] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: natRuleSchemaMake(),
},
}
rets["desc"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Optional user-defined text description of this ViNS.",
}
rets["restore"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
}
rets["vnfdev_restart"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
}
rets["vnfdev_redeploy"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
}
"ext_ip_addr": {
Type: schema.TypeString,
Computed: true,
Description: "IP address of the external connection (valid for ViNS connected to external network, ignored otherwise).",
},
rets["vins_id"] = &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "Unique ID of the ViNS. If ViNS ID is specified, then ViNS name, rg_id and account_id are ignored.",
}
return rets

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,120 +35,48 @@ package vins
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// On success this function returns a string, as returned by API vins/get, which could be unmarshalled
// into VinsGetResp structure
func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate ViNS by one of the following algorithms depending
// on the parameters passed:
// - if resource group ID is specified -> it looks for a ViNS at the RG level
// - if account ID is specifeid -> it looks for a ViNS at the account level
//
// If succeeded, it returns non empty string that contains JSON formatted facts about the
// ViNS as returned by vins/get API call.
// Otherwise it returns empty string and a meaningful error.
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for the Terraform resource Exists method.
//
func utilityDataVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*VINSDetailed, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
vins := &VINSDetailed{}
// make it possible to use "read" & "check presence" functions with ViNS ID set so
// that Import of ViNS resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
vinsId, argSet := d.GetOk("vins_id") // NB: vins_id is NOT present in vinsResource schema!
if argSet {
theId = vinsId.(int)
idSet = true
}
} else {
idSet = true
}
if idSet {
// ViNS ID is specified, try to get compute instance straight by this ID
log.Debugf("utilityVinsCheckPresence: locating ViNS by its ID %d", theId)
urlValues.Add("vinsId", fmt.Sprintf("%d", theId))
vinsFacts, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, urlValues)
if err != nil {
return "", err
}
return vinsFacts, nil
}
// ID was not set in the schema upon entering this function - work through ViNS name
// and Account / RG ID
vinsName, argSet := d.GetOk("name")
if !argSet {
// if ViNS name is not set. then we cannot locate ViNS
return "", fmt.Errorf("Cannot check ViNS presence if ViNS name is empty")
}
urlValues.Add("name", vinsName.(string))
urlValues.Add("show_all", "false")
log.Debugf("utilityVinsCheckPresence: preparing to locate ViNS name %s", vinsName.(string))
rgId, rgSet := d.GetOk("rg_id")
if rgSet {
log.Debugf("utilityVinsCheckPresence: limiting ViNS search to RG ID %d", rgId.(int))
urlValues.Add("rgId", fmt.Sprintf("%d", rgId.(int)))
}
accountId, accountSet := d.GetOk("account_id")
if accountSet {
log.Debugf("utilityVinsCheckPresence: limiting ViNS search to Account ID %d", accountId.(int))
urlValues.Add("accountId", fmt.Sprintf("%d", accountId.(int)))
}
apiResp, err := c.DecortAPICall(ctx, "POST", VinsSearchAPI, urlValues)
urlValues.Add("vinsId", strconv.Itoa(d.Get("vins_id").(int)))
vinsRaw, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, urlValues)
if err != nil {
return "", err
return nil, err
}
// log.Debugf("%s", apiResp)
// log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %s", VinsSearchAPI)
model := VinsSearchResp{}
err = json.Unmarshal([]byte(apiResp), &model)
err = json.Unmarshal([]byte(vinsRaw), vins)
if err != nil {
return "", err
return nil, err
}
return vins, nil
}
func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*VINSDetailed, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
vins := &VINSDetailed{}
urlValues.Add("vinsId", d.Id())
vinsRaw, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(vinsRaw), vins)
if err != nil {
return nil, err
}
return vins, nil
log.Debugf("utilityVinsCheckPresence: traversing decoded Json of length %d", len(model))
for index, item := range model {
if item.Name == vinsName.(string) {
if (accountSet && item.AccountID != accountId.(int)) ||
(rgSet && item.RgID != rgId.(int)) {
// double check that account ID and Rg ID match, if set in the schema
continue
}
log.Debugf("utilityVinsCheckPresence: match ViNS name %s / ID %d, account ID %d, RG ID %d at index %d",
item.Name, item.ID, item.AccountID, item.RgID, index)
// element returned by API vins/search does not contain all information we may need to
// manage ViNS, so we have to get detailed info by calling API vins/get
rqValues := &url.Values{}
rqValues.Add("vinsId", fmt.Sprintf("%d", item.ID))
vinsGetResp, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, rqValues)
if err != nil {
return "", err
}
return vinsGetResp, nil
}
}
return "", fmt.Errorf("Cannot find ViNS name %s. Check name and/or RG ID & Account ID and your access rights", vinsName.(string))
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityVinsAuditsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (VINSAuditsList, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
auditsList := VINSAuditsList{}
urlValues.Add("vinsId", strconv.Itoa(d.Get("vins_id").(int)))
auidtsRaw, err := c.DecortAPICall(ctx, "POST", VinsAuditsAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(auidtsRaw), &auditsList)
if err != nil {
return nil, err
}
return auditsList, nil
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityVinsExtNetListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ExtNetList, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
extNet := ExtNetList{}
urlValues.Add("vinsId", strconv.Itoa(d.Get("vins_id").(int)))
extNetRaw, err := c.DecortAPICall(ctx, "POST", VinsExtNetListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(extNetRaw), &extNet)
if err != nil {
return nil, err
}
return extNet, nil
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityVinsIpListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (IPList, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
ips := IPList{}
urlValues.Add("vinsId", strconv.Itoa(d.Get("vins_id").(int)))
auidtsRaw, err := c.DecortAPICall(ctx, "POST", VinsIpListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(auidtsRaw), &ips)
if err != nil {
return nil, err
}
return ips, nil
}

View File

@@ -3,6 +3,7 @@ Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -43,8 +44,8 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (VinsList, error) {
vinsList := VinsList{}
func utilityVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (VINSList, error) {
vinsList := VINSList{}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}

View File

@@ -0,0 +1,70 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func utilityVinsListDeletedCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (VINSList, error) {
vinsList := VINSList{}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
}
log.Debugf("utilityVinsListDeletedCheckPresence")
vinsListRaw, err := c.DecortAPICall(ctx, "POST", VinsListDeletedAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(vinsListRaw), &vinsList)
if err != nil {
return nil, err
}
return vinsList, nil
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityVinsNatRuleListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (NATRuleList, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
natRuleList := NATRuleList{}
urlValues.Add("vinsId", strconv.Itoa(d.Get("vins_id").(int)))
auidtsRaw, err := c.DecortAPICall(ctx, "POST", VinsNatRuleListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(auidtsRaw), &natRuleList)
if err != nil {
return nil, err
}
return natRuleList, nil
}

View File

@@ -317,7 +317,7 @@ func dataSourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"snapshots": {

View File

@@ -399,7 +399,7 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"snapshots": {

View File

@@ -72,7 +72,7 @@ type Disk struct {
SepType string `json:"sepType"`
SepID int `json:"sepId"` // NOTE: absent from compute/get output
SizeMax int `json:"sizeMax"`
SizeUsed int `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
SizeUsed float64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
Snapshots []Snapshot `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`

View File

@@ -548,7 +548,7 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Computed: true,
},
"size_used": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Computed: true,
},
"snapshots": {

View File

@@ -72,7 +72,7 @@ type DiskRecord struct {
SepType string `json:"sepType"`
SepID int `json:"sepId"` // NOTE: absent from compute/get output
SizeMax int `json:"sizeMax"`
SizeUsed int `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
SizeUsed float64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
Snapshots []SnapshotRecord `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package status
type Status = string
@@ -12,22 +44,26 @@ var (
// Status available for:
// - Compute
// - Disk
// - Vins
Enabled Status = "ENABLED"
// Enabling in process
// Status available for:
// - Disk
// - Vins
Enabling Status = "ENABLING"
// An object disabled for operations
// Status available for:
// - Compute
// - Disk
// - Vins
Disabled Status = "DISABLED"
// Disabling in process
// Status available for:
// - Disk
// - Vins
Disabling Status = "DISABLING"
// An object model has been created in the database
@@ -35,6 +71,7 @@ var (
// - Image
// - Disk
// - Compute
// - Vins
Modeled Status = "MODELED"
// In the process of creation
@@ -47,6 +84,7 @@ var (
// - Image
// - Disk
// - Compute
// - Vins
Created Status = "CREATED"
// Physical resources are allocated for the object
@@ -63,6 +101,7 @@ var (
// Status available for:
// - Disk
// - Compute
// - Vins
Destroying Status = "DESTROYING"
// Permanently deleted
@@ -70,16 +109,19 @@ var (
// - Image
// - Disk
// - Compute
// - Vins
Destroyed Status = "DESTROYED"
// Deleting in progress to Trash
// Status available for:
// - Compute
// - Vins
Deleting Status = "DELETING"
// Deleted to Trash
// Status available for:
// - Compute
// - Vins
Deleted Status = "DELETED"
// Deleted from storage
@@ -91,4 +133,9 @@ var (
// Status available for:
// - Compute
Redeploying Status = "REDEPLOYING"
// The resource is not bound to vnf device
// Status available for:
// - vins vnf
Stashed Status = "STASHED"
)

View File

@@ -1,3 +1,35 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package techstatus
type TechStatus = string

View File

@@ -1,9 +0,0 @@
terraform {
required_providers {
decort = {
source = "digitalenergy.online/decort/decort"
version = "3.2.2"
}
}
}

View File

@@ -0,0 +1,37 @@
/*
Пример использования
Получение информации о k8s кластере
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_k8s" "k8s" {
#id кластера
#обязательный параметр
#тип - число
k8s_id = 49304
}
output "output_k8s" {
value = data.decort_k8s.k8s
}

View File

@@ -0,0 +1,50 @@
/*
Пример использования
Получение списка доступных кластеров
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_k8s_list" "k8s_list" {
#включение удаленных k8s в результат
#опциональный параметр
#тип - будев тип
#если не задан - выводятся все неудаленные данные
include_deleted = true
#номер страницы для отображения
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
page = 1
#размер страницы
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
size = 1
}
output "output_k8s_list" {
value = data.decort_k8s_list.k8s_list
}

View File

@@ -0,0 +1,45 @@
/*
Пример использования
Получение списка доступных кластеров включая удаленные
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_k8s_list_deleted" "k8s_list_deleted" {
#номер страницы для отображения
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
page = 1
#размер страницы
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
size = 1
}
output "output_k8s_list_deleted" {
value = data.decort_k8s_list_deleted.k8s_list_deleted
}

View File

@@ -0,0 +1,42 @@
/*
Пример использования
Получение информации о k8s кластере
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_k8s_wg" "k8s_wg" {
#id кластера
#обязательный параметр
#тип - число
k8s_id = 49304
#id группы воркеров
#обязательный параметр
#тип - число
wg_id = 43329
}
output "output_k8s_wg" {
value = data.decort_k8s.k8s
}

View File

@@ -0,0 +1,37 @@
/*
Пример использования
Получение списка доступных групп воркеров в кластере
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_k8s_wg_list" "k8s_wg_list" {
#id кластера
#обязательный параметр
#тип - число
k8s_id = 49304
}
output "output_k8s_wg_list" {
value = data.decort_k8s_wg_list.k8s_wg_list
}

View File

@@ -0,0 +1,38 @@
/*
Пример использования
Получение данных о vins
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins" "vins" {
#обязательный параметр
#id жедаемого vins
#тип - число
vins_id = 10101
}
output "test" {
value = data.decort_vins.vins
}

View File

@@ -0,0 +1,38 @@
/*
Пример использования
Получение списка vins audits
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins_audits" "vins_audits" {
#обязательный параметр
#id жедаемого vins
#тип - число
vins_id = 10101
}
output "test" {
value = data.decort_vins_audits.vins_audits
}

View File

@@ -0,0 +1,37 @@
/*
Пример использования
Получение списка vins extnet
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins_ext_net_list" "vins_ext_net_list" {
#обязательный параметр
#id жедаемого vins
#тип - число
vins_id = 10101
}
output "test" {
value = data.decort_vins_ext_net_list.vins_ext_net_list
}

View File

@@ -0,0 +1,39 @@
/*
Пример использования
Получение списка vins_ip
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins_ip_list" "vins_ip_list" {
#обязательный параметр
#id жедаемого vins
#тип - число
vins_id = 10101
}
output "test" {
value = data.decort_vins_ip_list.vins_ip_list
}

View File

@@ -0,0 +1,42 @@
/*
Пример использования
Получение списка удаленных vins
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins_list_deleted" "vins_list_deleted" {
#кол-во страниц для вывода
#опицональный параметр
#тип - число
page = 1
#размер страницы
#опицональный параметр
#тип - число
size = 1
}
output "test" {
value = data.decort_vins_list_deleted.vinslist_deleted
}

View File

@@ -0,0 +1,39 @@
/*
Пример использования
Получение списка natRule vins
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через 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_vins_nat_rule_list" "vins_nat_rule_list" {
#обязательный параметр
#id жедаемого vins
#тип - число
vins_id = 10101
}
output "test" {
value = data.decort_vins_nat_rule_list.vins_nat_rule_list
}

View File

@@ -33,6 +33,7 @@ resource "decort_disk" "acl" {
restore = true
permanently = true
reason = "delete"
shareable = false
iotune {
read_bytes_sec = 0
read_bytes_sec_max = 0

Some files were not shown because too many files have changed in this diff Show More