Compare commits

..

1 Commits

Author SHA1 Message Date
kjubybot
9d15af9259 k8s, k8s_wg: single worker add/delete support; github actions support 2022-03-28 15:31:01 +03:00
503 changed files with 5173 additions and 51297 deletions

View File

@@ -1,4 +1,4 @@
name: Release
name: Release to registry
on:
push:
tags:
@@ -17,9 +17,9 @@ jobs:
run: git fetch --force --tags
- name: Setup Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.17
- name: Import GPG key
id: import_gpg
@@ -29,7 +29,7 @@ jobs:
passphrase: ${{ secrets.PASSPHRASE }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
uses: goreleaser/goreleaser-action@v2
with:
args: release --rm-dist --release-notes CHANGELOG.md
env:

1
.gitignore vendored
View File

@@ -2,4 +2,3 @@ decort/vendor/
examples/
url_scrapping/
terraform-provider-decort*
.vscode/

View File

@@ -1,35 +0,0 @@
linters:
enable:
- bodyclose
- decorder
- dogsled
- errorlint
- exportloopref
#- gocognit - disabled till better times
- goconst
- gocyclo
- gosec
- ifshort
- makezero
#- nestif - disabled till better times
- nilerr
- prealloc
- unconvert
- unparam
linters-settings:
errcheck:
exclude-functions:
- (*github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.ResourceData).Set
staticcheck:
go: "1.18"
checks:
- all
- -SA1019
nestif:
min-complexity: 7
gocyclo:
min-complexity: 40
issues:
max-same-issues: 0

View File

@@ -4,7 +4,6 @@ before:
builds:
- env:
- CGO_ENABLED=0
main: ./cmd/decort
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
@@ -16,12 +15,9 @@ builds:
goarch:
- amd64
- '386'
- arm64
ignore:
- goos: darwin
goarch: '386'
- goos: windows
goarch: arm64
binary: '{{ .ProjectName }}_v{{ .Version }}'
archives:
- format: zip

View File

@@ -1,33 +1,16 @@
### Version 3.3.0
## 2.0
### Bug fixes
### New data sources
- image
- image\_list
- grid
- grid\_list
- image\_list\_stacks
- Fix bug with getting k8s_wg from import
- Fix bug with getting k8s from import
### Features
- Add data_source k8s
- Add data_source k8s_list
- Add data_source k8s_list_deleted
- Add data_source k8s_wg_list
- Add data_source k8s_wg
- Add a vins_id to the k8s schema/state
- Add a ips from computes to the k8s group workers in schema/state
- Add a ips from computes to the k8s masters in schema/state
- Add a ips from computes to the k8s_wg in schema/state
- Change data_source vins, the schema/state is aligned with the platform
- Add data_source vins_audits
- Add data_source vins_ext_net_list
- Add data_source vins_ip_list
- Change data_source vins_list, the schema/state is aligned with the platform
- Add data_source vins_list_deleted
- Add data_source vins_nat_rule_list
- Add status checker for vins resource
- Add the ability to create and update ip reservations
- Add the ability to create and update nat_rule reservations
- Add enable/disable functionality for vins resource
- Add the ability to restart vnfDev
- Add the ability to redeploy vnfDev
- Add the ability to import vins
- Add warnings handling, which does not interrupt the work when the state is successfully created
### New resources
- image
- virtual\_image
- cdrom\_image
- delete\_images
- k8s
- k8s\_wg

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.3.0/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

@@ -4,30 +4,14 @@ NAMESPACE=decort
NAME=terraform-provider-decort
#BINARY=terraform-provider-${NAME}
BINARY=${NAME}.exe
WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH}
MAINPATH = ./cmd/decort/
VERSION=1.1
VERSION=0.2
#OS_ARCH=darwin_amd64
OS_ARCH=windows_amd64
#OS_ARCH=linux_amd64
default: install
image:
GOOS=linux GOARCH=amd64 go build -o terraform-provider-decort ./cmd/decort/
docker build . -t rudecs/tf:3.2.2
rm terraform-provider-decort
lint:
golangci-lint run --timeout 600s
st:
go build -o ${BINARY} ${MAINPATH}
cp ${BINARY} ${WORKPATH}
rm ${BINARY}
build:
go build -o ${BINARY} ${MAINPATH}
go build -o ${BINARY}
release:
GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64
@@ -52,4 +36,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

@@ -1,56 +1,32 @@
# terraform-provider-decort
Terraform provider для платформы Digital Energy Cloud Orchestration Technology (DECORT)
Внимание: провайдер версии 3.x разработан для DECORT API 3.8.x.
Внимание: провайдер версии rc-1.25 разработан для DECORT API 3.7.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_ADMIN_MODE.
Вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
## Возможности провайдера
- Работа с Compute instances,
- Работа с disks,
- Работа с Compute instances,
- Работа с disks,
- Работа с k8s,
- Работа с virtual network segments,
- Работа с image,
- Работа с reource groups,
- Работа с VINS,
- Работа с pfw,
- Работа с accounts,
- Работа с snapshots,
- Работа с pcidevice,
- Работа с sep,
- Работа с vgpu,
- Работа с bservice,
- Работа с extnets,
- Работа с locations,
- Работа с load balancer.
- Работа с accounts.
Вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
## Начало
Старт возможен по двум путям:
Старт возможен по двум путям:
1. Установка через собранные пакеты.
2. Ручная установка.
### Установка через собранные пакеты.
1. Скачайте и установите terraform по ссылке: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started
2. Создайте файл `main.tf` и добавьте в него следующий блок.
```terraform
provider "decort" {
authenticator = "oauth2"
@@ -61,62 +37,45 @@ provider "decort" {
allow_unverified_ssl = true
}
```
3. Выполните команду
```
terraform init
```
Провайдер автоматически будет установлен на ваш компьютер из terraform registry.
### Ручная установка
1. Скачайте и установите Go по ссылке: https://go.dev/dl/
2. Скачайте и установите terraform по ссылке: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started
3. Склонируйте репозиторий с провайдером, выполнив команду:
```bash
git clone https://github.com/rudecs/terraform-provider-decort.git
```
4. Перейдите в скачанную папку с провайдером и выполните команду
```bash
go build -o terraform-provider-decort
```
Если вы знаете как устроен _makefile_, то можно изменить в файле `Makefile` параметры под вашу ОС и выполнить команду
```bash
make build
```
5. Полученный файл необходимо поместить:
Linux:
Linux:
```bash
~/.terraform.d/plugins/${host_name}/${namespace}/${type}/${version}/${target}
```
Windows:
```powershell
%APPDATA%\terraform.d\plugins\${host_name}\${namespace}\${type}\${version}\${target}
%APPDATA%\terraform.d\plugins\${host_name}/${namespace}/${type}/${version}/${target}
```
ВНИМАНИЕ: для ОС Windows `%APP_DATA%` является каталогом, в котором будут помещены будущие файлы terraform.
Где:
- host_name - имя хоста, держателя провайдера, например, digitalenergy.online
- namespace - пространство имен хоста, например decort
- namespace - пространство имен хоста, например decort
- type - тип провайдера, может совпадать с пространством имен, например, decort
- version - версия провайдера, например 1.2
- target - версия ОС, например windows_amd64
6. После этого, создайте файл `main.tf`.
7. Добавьте в него следующий блок
```terraform
terraform {
required_providers {
@@ -127,39 +86,29 @@ terraform {
}
}
```
В поле `version` указывается версия провайдера.
Обязательный параметр
Тип поля - строка
ВНИМАНИЕ: Версии в блоке и в репозитории, в который был помещен провайдер должны совпадать!
В поле `source` помещается путь до репозитория с версией вида:
```bash
${host_name}/${namespace}/${type}
```
ВНИМАНИЕ: все параметры должны совпадать с путем репозитория, в котором помещен провайдер.
ВНИМАНИЕ: все параметры должны совпадать с путем репозитория, в котором помещен провайдер.
8. В консоле выполнить команду
8. В консоле выполнить команду
```bash
terraform init
```
9. Если все прошло хорошо - ошибок не будет.
9. Если все прошло хорошо - ошибок не будет.
Более подробно о сборке провайдера можно найти по ссылке: https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers
## Примеры работы
Примеры работы можно найти:
- На вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
Примеры работы можно найти на:
- Вики проекта: https://github.com/rudecs/terraform-provider-decort/wiki
- В папке `samples`
Схемы к terraform'у доступны:
- В папке `docs`
Хорошей работы!

View File

@@ -1,57 +1,34 @@
# terraform-provider-decort
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:
- DECORT API 3.7.x versions - provider verion rc-1.25
NOTE: provider rc-1.25 is designed for DECORT API 3.7.x. For older API versions please use:
- 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)
## Working modes
The provider support two working modes:
- User mode,
- Administator mode.
Use flag DECORT_ADMIN_MODE for swithcing beetwen modes.
See user guide at https://github.com/rudecs/terraform-provider-decort/wiki
## Features
- Work with Compute instances,
- Work with disks,
- Work with Compute instances,
- Work with disks,
- Work with k8s,
- Work with virtual network segments,
- Work with image,
- Work with reource groups,
- Work with VINS,
- Work with pfw,
- Work with accounts,
- Work with snapshots,
- Work with pcidevice.
- Work with sep,
- Work with vgpu,
- Work with bservice,
- Work with extnets,
- Work with locations,
- Work with load balancers.
- Work with accounts.
This provider supports Import operations on pre-existing resources.
See user guide at https://github.com/rudecs/terraform-provider-decort/wiki
## Get Started
Two ways for starting:
Two ways for starting:
1. Installing via binary packages
2. Manual installing
### Installing via binary packages
1. Download and install terraform: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started
2. Create a file `main.tf` and add to it next section.
```terraform
provider "decort" {
authenticator = "oauth2"
@@ -62,62 +39,45 @@ provider "decort" {
allow_unverified_ssl = true
}
```
3. Execute next command
```
terraform init
```
The Provider will automatically install on your computer from the terrafrom registry.
### Manual installing
1. Download and install Go Programming Language: https://go.dev/dl/
2. Download and install terraform: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started
3. Clone provider's repo:
```bash
git clone https://github.com/rudecs/terraform-provider-decort.git
```
4. Change directory to clone provider's and execute next command
```bash
go build -o terraform-provider-decort
```
If you have experience with _makefile_, you can change `Makefile`'s paramters and execute next command
```bash
make build
```
5. Now move compilled file to:
Linux:
Linux:
```bash
~/.terraform.d/plugins/${host_name}/${namespace}/${type}/${version}/${target}
```
Windows:
```powershell
%APPDATA%\terraform.d\plugins\${host_name}/${namespace}/${type}/${version}/${target}
```
NOTE: for Windows OS `%APP_DATA%` is a cataloge, where will place terraform files.
Example:
- host_name - digitalenergy.online
- namespace - decort
- namespace - decort
- type - decort
- version - 1.2
- target - windows_amd64
6. After all, create a file `main.tf`.
7. Add to the file next code section
```terraform
terraform {
required_providers {
@@ -128,22 +88,18 @@ terraform {
}
}
```
`version`- field for provider's version
Required
String
Note: Versions in code section and in a repository must be equal!
`source` - path to repository with provider's version
```bash
${host_name}/${namespace}/${type}
```
NOTE: all paramters must be equal to the repository path!
8. Execute command in your terminal
8. Execute command in your terminal
```bash
terraform init
```
@@ -153,12 +109,7 @@ terraform init
More details about the provider's building process: https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers
## Examples and Samples
- Examples: https://github.com/rudecs/terraform-provider-decort/wiki
- Samples: see in repository `samples`
Terraform schemas in:
- See in repository `docs`
- Samples: in repository `samples`
Good work!

View File

@@ -1,9 +1,6 @@
/*
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>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,22 +15,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package constants
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
// LimitMaxVinsPerResgroup set maximum number of VINs instances per Resource Group
const LimitMaxVinsPerResgroup = 4
const LimitMaxVinsPerResgroup=4
// MaxSshKeysPerCompute sets maximum number of user:ssh_key pairs to authorize when creating new compute
const MaxSshKeysPerCompute = 12
const MaxSshKeysPerCompute=12
// MaxExtraDisksPerCompute sets maximum number of extra disks that can be added when creating new compute
const MaxExtraDisksPerCompute = 12
const MaxExtraDisksPerCompute=12
// MaxNetworksPerCompute sets maximum number of vNICs per compute
const MaxNetworksPerCompute = 8
const MaxNetworksPerCompute=8
// MaxCpusPerCompute sets maximum number of vCPUs per compute
const MaxCpusPerCompute = 128
const MaxCpusPerCompute=128
// MinRamPerCompute sets minimum amount of RAM per compute in MB
const MinRamPerCompute = 128
const MinRamPerCompute=128

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,11 +15,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"io/ioutil"
@@ -29,15 +33,15 @@ import (
"net/url"
"strconv"
"strings"
"time"
// "time"
log "github.com/sirupsen/logrus"
jwt "github.com/golang-jwt/jwt/v4"
"github.com/dgrijalva/jwt-go"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/terraform"
)
// enumerated constants that define authentication modes
@@ -88,7 +92,8 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
decort_username: "",
}
allow_unverified_ssl := d.Get("allow_unverified_ssl").(bool)
var allow_unverified_ssl bool
allow_unverified_ssl = d.Get("allow_unverified_ssl").(bool)
if ret_config.controller_url == "" {
return nil, fmt.Errorf("Empty DECORT cloud controller URL provided.")
@@ -131,12 +136,15 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
if allow_unverified_ssl {
log.Warn("ControllerConfigure: allow_unverified_ssl is set - will not check certificates!")
transCfg := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} //nolint:gosec
transCfg := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
ret_config.cc_client = &http.Client{
Transport: transCfg,
Timeout: Timeout180s,
}
} else {
ret_config.cc_client = &http.Client{}
ret_config.cc_client = &http.Client{
Timeout: Timeout180s, // time.Second * 30,
}
}
switch ret_config.auth_mode_code {
@@ -186,7 +194,7 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
return ret_config, nil
}
func (config *ControllerCfg) GetDecortUsername() string {
func (config *ControllerCfg) getDecortUsername() string {
return config.decort_username
}
@@ -326,7 +334,7 @@ func (config *ControllerCfg) validateLegacyUser() (bool, error) {
return true, nil
}
func (config *ControllerCfg) DecortAPICall(ctx context.Context, method string, api_name string, url_values *url.Values) (json_resp string, err error) { //nolint:unparam
func (config *ControllerCfg) decortAPICall(method string, api_name string, url_values *url.Values) (json_resp string, err error) {
// This is a convenience wrapper around standard HTTP request methods that is aware of the
// authorization mode for which the provider was initialized and compiles request accordingly.
@@ -362,9 +370,6 @@ func (config *ControllerCfg) DecortAPICall(ctx context.Context, method string, a
if err != nil {
return "", err
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Length", strconv.Itoa(len(params_str)))
req.Header.Set("Accept", "application/json")
@@ -373,34 +378,28 @@ func (config *ControllerCfg) DecortAPICall(ctx context.Context, method string, a
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", config.jwt))
}
var resp *http.Response
var body []byte
for i := 0; i < 5; i++ {
resp, err = config.cc_client.Do(req)
if err != nil {
return "", err
}
resp, err := config.cc_client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
resp.Body.Close()
log.Debugf("decortAPICall: %s %s\n %s", method, api_name, body)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
log.Debugf("decortAPICall: %s %s\n %s", method, api_name, body)
if resp.StatusCode == http.StatusOK {
return string(body), nil
} else {
if resp.StatusCode == http.StatusInternalServerError {
log.Warnf("got 500, retrying %d/5", i+1)
time.Sleep(time.Second * 5)
continue
}
return "", fmt.Errorf("decortAPICall: unexpected status code %d when calling API %q with request Body %q. Respone:\n%s",
resp.StatusCode, req.URL, params_str, body)
}
if resp.StatusCode == http.StatusOK {
return string(body), nil
} else {
return "", fmt.Errorf("decortAPICall: unexpected status code %d when calling API %q with request Body %q. Respone:\n%s",
resp.StatusCode, req.URL, params_str, body)
}
return "", fmt.Errorf("decortAPICall: unexpected status code %d when calling API %q with request Body %q. Respone:\n%s",
resp.StatusCode, req.URL, params_str, body)
/*
if resp.StatusCode == StatusServiceUnavailable {
return nil, fmt.Errorf("decortAPICall method called for incompatible authorization mode %q.", config.auth_mode_txt)
}
*/
}

View File

@@ -0,0 +1,132 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
// "net/url"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenAccount(d *schema.ResourceData, acc_facts string) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceAccountExists(...) method
// log.Debugf("flattenAccount: ready to decode response body from %q", CloudspacesGetAPI)
details := AccountRecord{}
err := json.Unmarshal([]byte(acc_facts), &details)
if err != nil {
return err
}
log.Debugf("flattenAccount: decoded Account name %q / ID %d, status %q", details.Name, details.ID, details.Status)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("name", details.Name)
d.Set("status", details.Status)
return nil
}
func dataSourceAccountRead(d *schema.ResourceData, m interface{}) error {
acc_facts, err := utilityAccountCheckPresence(d, m)
if acc_facts == "" {
// if empty string is returned from utilityAccountCheckPresence then there is no
// such account and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty in this case
return err
}
return flattenAccount(d, acc_facts)
}
func dataSourceAccount() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Read: dataSourceAccountRead,
Timeouts: &schema.ResourceTimeout{
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Description: "Name of the account. Names are case sensitive and unique.",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the account. If account ID is specified, then account name is ignored.",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of the account.",
},
/* We keep the following attributes commented out, as we are not implementing account
management with Terraform plugin, so we do not need this extra info.
"quota": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchema(), // this is a dictionary
},
Description: "Quotas on the resources for this account and all its resource groups.",
},
"resource_groups": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema {
Type: schema.TypeInt,
},
Description: "IDs of resource groups in this account."
},
"vins": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema {
Type: schema.TypeInt,
},
Description: "IDs of VINSes created at the account level."
},
*/
},
}
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,31 +16,23 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package kvmvm
package decort
import (
"context"
"encoding/json"
"fmt"
// "net/url"
"github.com/rudecs/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
@@ -76,15 +66,88 @@ func parseComputeDisksToExtraDisks(disks []DiskRecord) []interface{} {
return result
}
func findBootDisk(disks []DiskRecord) *DiskRecord {
for _, d := range disks {
if d.Type == "B" {
return &d
// NOTE: this is a legacy function, which is not used as of rc-1.10
// Use "parseComputeDisksToExtraDisks" instead
func parseComputeDisks(disks []DiskRecord) []interface{} {
// Return value was designed to d.Set("disks",) item of dataSourceCompute schema
// However, this item was excluded from the schema as it is not directly
// managed through Terraform
length := len(disks)
log.Debugf("parseComputeDisks: called for %d disks", length)
/*
if length == 1 && disks[0].Type == "B" {
// there is only one disk in the list and it is a boot disk
// as we skip boot disks, the result will be of 0 lenght
length = 0
}
*/
result := []interface{}{}
if length == 0 {
return result
}
for _, value := range disks {
/*
if value.Type == "B" {
// skip boot disk when parsing the list of disks
continue
}
*/
elem := make(map[string]interface{})
// keys in this map should correspond to the Schema definition
// as returned by dataSourceDiskSchemaMake()
elem["name"] = value.Name
elem["disk_id"] = value.ID
elem["account_id"] = value.AccountID
elem["account_name"] = value.AccountName
elem["description"] = value.Desc
elem["image_id"] = value.ImageID
elem["size"] = value.SizeMax
elem["type"] = value.Type
elem["sep_id"] = value.SepID
elem["sep_type"] = value.SepType
elem["pool"] = value.Pool
// elem["status"] = value.Status
// elem["tech_status"] = value.TechStatus
elem["compute_id"] = value.ComputeID
result = append(result, elem)
}
return result
}
func parseBootDiskSize(disks []DiskRecord) int {
// this return value will be used to d.Set("boot_disk_size",) item of dataSourceCompute schema
if len(disks) == 0 {
return 0
}
for _, value := range disks {
if value.Type == "B" {
return value.SizeMax
}
}
// some computes don't have a boot disk, so...
return &DiskRecord{}
return 0
}
func parseBootDiskId(disks []DiskRecord) uint {
// this return value will be used to d.Set("boot_disk_id",) item of dataSourceCompute schema
if len(disks) == 0 {
return 0
}
for _, value := range disks {
if value.Type == "B" {
return value.ID
}
}
return 0
}
// Parse the list of interfaces from compute/get response into a list of networks
@@ -113,6 +176,71 @@ func parseComputeInterfacesToNetworks(ifaces []InterfaceRecord) []interface{} {
return result
}
/*
func parseComputeInterfacesToNetworks(ifaces []InterfaceRecord) []map[string]interface{} {
// return value will be used to d.Set("network") item of dataSourceCompute schema
length := len(ifaces)
log.Debugf("parseComputeInterfacesToNetworks: called for %d ifaces", length)
result := make([]map[string]interface{}, length, length)
for i, value := range ifaces {
elem := make(map[string]interface{})
// Keys in this map should correspond to the Schema definition
// as returned by networkSubresourceSchemaMake()
elem["net_id"] = value.NetID
elem["net_type"] = value.NetType
elem["ip_address"] = value.IPAddress
elem["mac"] = value.MAC
// log.Debugf(" element %d: net_id=%d, net_type=%s", i, value.NetID, value.NetType)
result[i] = elem
}
return result
}
*/
// NOTE: this function is retained for historical purposes and actually not used as of rc-1.10
func parseComputeInterfaces(ifaces []InterfaceRecord) []map[string]interface{} {
// return value was designed to d.Set("interfaces",) item of dataSourceCompute schema
// However, this item was excluded from the schema as it is not directly
// managed through Terraform
length := len(ifaces)
log.Debugf("parseComputeInterfaces: called for %d ifaces", length)
result := make([]map[string]interface{}, length, length)
for i, value := range ifaces {
// Keys in this map should correspond to the Schema definition
// as returned by dataSourceInterfaceSchemaMake()
elem := make(map[string]interface{})
elem["net_id"] = value.NetID
elem["net_type"] = value.NetType
elem["ip_address"] = value.IPAddress
elem["netmask"] = value.NetMask
elem["mac"] = value.MAC
elem["default_gw"] = value.DefaultGW
elem["name"] = value.Name
elem["connection_id"] = value.ConnID
elem["connection_type"] = value.ConnType
/* TODO: add code to parse QoS
qos_schema := interfaceQosSubresourceSchemaMake()
qos_schema.Set("egress_rate", value.QOS.ERate)
qos_schema.Set("ingress_rate", value.QOS.InRate)
qos_schema.Set("ingress_burst", value.QOS.InBurst)
elem["qos"] = qos_schema
*/
result[i] = elem
}
return result
}
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.
@@ -139,6 +267,8 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
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
d.Set("boot_disk_size", parseBootDiskSize(model.Disks))
d.Set("boot_disk_id", parseBootDiskId(model.Disks)) // we may need boot disk ID in resize operations
d.Set("image_id", model.ImageID)
d.Set("description", model.Desc)
d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion
@@ -151,13 +281,6 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
d.Set("started", false)
}
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 {
@@ -182,31 +305,27 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
return nil
}
func dataSourceComputeRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
compFacts, err := utilityComputeCheckPresence(ctx, d, m)
func dataSourceComputeRead(d *schema.ResourceData, m interface{}) error {
compFacts, err := utilityComputeCheckPresence(d, m)
if compFacts == "" {
// if empty string is returned from utilityComputeCheckPresence then there is no
// such Compute and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
return diag.FromErr(err)
return err
}
if err = flattenCompute(d, compFacts); err != nil {
return diag.FromErr(err)
}
return nil
return flattenCompute(d, compFacts)
}
func DataSourceCompute() *schema.Resource {
func dataSourceCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeRead,
Read: dataSourceComputeRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
@@ -293,6 +412,7 @@ func DataSourceCompute() *schema.Resource {
"extra_disks": {
Type: schema.TypeSet,
Computed: true,
MaxItems: MaxExtraDisksPerCompute,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
@@ -313,13 +433,24 @@ func DataSourceCompute() *schema.Resource {
"network": {
Type: schema.TypeSet,
Optional: true,
MaxItems: constants.MaxNetworksPerCompute,
MaxItems: MaxNetworksPerCompute,
Elem: &schema.Resource{
Schema: networkSubresourceSchemaMake(),
},
Description: "Network connection(s) for this compute.",
},
/*
"interfaces": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: interfaceSubresourceSchemaMake(),
},
Description: "Specification for the virtual NICs configured on this compute instance.",
},
*/
"os_users": {
Type: schema.TypeList,
Computed: true,
@@ -347,6 +478,26 @@ func DataSourceCompute() *schema.Resource {
Default: true,
Description: "Is compute started.",
},
/*
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current model status of this compute instance.",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "Current technical status of this compute instance.",
},
"internal_ip": {
Type: schema.TypeString,
Computed: true,
Description: "Internal IP address of this Compute.",
},
*/
},
}
}

201
decort/data_source_disk.go Normal file
View File

@@ -0,0 +1,201 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
// "net/url"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func flattenDisk(d *schema.ResourceData, disk_facts string) error {
// This function expects disk_facts string to contain a response from disks/get API
//
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceDiskExists(...) method. Use utilityDiskCheckPresence instead.
log.Debugf("flattenDisk: ready to unmarshal string %s", disk_facts)
model := DiskRecord{}
err := json.Unmarshal([]byte(disk_facts), &model)
if err != nil {
return err
}
log.Debugf("flattenDisk: disk ID %d, disk AccountID %d", model.ID, model.AccountID)
d.SetId(fmt.Sprintf("%d", model.ID))
// d.Set("disk_id", model.ID) - we should NOT update disk_id in the schema. If it was set - it is already set, if it wasn't - we shouldn't
d.Set("name", model.Name)
d.Set("account_id", model.AccountID)
d.Set("account_name", model.AccountName)
d.Set("size", model.SizeMax)
// d.Set("sizeUsed", model.SizeUsed)
d.Set("type", model.Type)
d.Set("image_id", model.ImageID)
d.Set("sep_id", model.SepID)
d.Set("sep_type", model.SepType)
d.Set("pool", model.Pool)
// d.Set("compute_id", model.ComputeID)
d.Set("description", model.Desc)
return nil
}
func dataSourceDiskRead(d *schema.ResourceData, m interface{}) error {
disk_facts, err := utilityDiskCheckPresence(d, m)
if disk_facts == "" {
// if empty string is returned from utilityDiskCheckPresence then there is no
// such Disk and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
return err
}
return flattenDisk(d, disk_facts)
}
func dataSourceDiskSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Description: "Name of this disk. NOTE: disk names are NOT unique within an account. If disk ID is specified, disk name is ignored.",
},
"disk_id": {
Type: schema.TypeInt,
Optional: true,
Description: "ID of the disk to get. If disk ID is specified, then disk name and account ID are ignored.",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Description: "ID of the account this disk belongs to. If disk ID is specified, then account ID is ignored.",
},
// The rest of the data source Disk schema are all computed
"sep_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Storage end-point provider serving this disk.",
},
"pool": {
Type: schema.TypeString,
Computed: true,
Description: "Pool where this disk is located.",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "Size of the disk in GB.",
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of this disk. E.g. D for data disks, B for boot.",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "User-defined text description of this disk.",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account this disk belongs to. If account ID is specified, account name is ignored.",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the image, which this disk was cloned from (valid for disk clones only).",
},
"sep_type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of the storage end-point provider serving this disk.",
},
/*
"snapshots": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource {
Schema: snapshotSubresourceSchemaMake(),
},
Description: "List of user-created snapshots for this disk."
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current model status of this disk.",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "Current technical status of this disk.",
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the compute instance where this disk is attached to, or 0 for unattached disk.",
},
*/
}
return rets
}
func dataSourceDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Read: dataSourceDiskRead,
Timeouts: &schema.ResourceTimeout{
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceDiskSchemaMake(),
}
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,26 +16,18 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package grid
package decort
import (
"context"
"strconv"
"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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenGrid(d *schema.ResourceData, grid *Grid) {
@@ -47,12 +37,13 @@ func flattenGrid(d *schema.ResourceData, grid *Grid) {
d.Set("guid", grid.Guid)
d.Set("location_code", grid.LocationCode)
d.Set("id", grid.Id)
return
}
func dataSourceGridRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
grid, err := utilityGridCheckPresence(ctx, d, m)
func dataSourceGridRead(d *schema.ResourceData, m interface{}) error {
grid, err := utilityGridCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(strconv.Itoa(grid.Id))
flattenGrid(d, grid)
@@ -93,15 +84,15 @@ func dataSourceGetGridSchemaMake() map[string]*schema.Schema {
}
}
func DataSourceGrid() *schema.Resource {
func dataSourceGrid() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceGridRead,
Read: dataSourceGridRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceGetGridSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,26 +16,17 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package grid
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenGridList(gl GridList) []map[string]interface{} {
@@ -57,10 +46,10 @@ func flattenGridList(gl GridList) []map[string]interface{} {
return res
}
func dataSourceGridListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
gridList, err := utilityGridListCheckPresence(ctx, d, m)
func dataSourceGridListRead(d *schema.ResourceData, m interface{}) error {
gridList, err := utilityGridListCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
id := uuid.New()
d.SetId(id.String())
@@ -123,15 +112,15 @@ func dataSourceGridSchemaMake() map[string]*schema.Schema {
}
}
func DataSourceGridList() *schema.Resource {
func dataSourceGridList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceGridListRead,
Read: dataSourceGridListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceGridListSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,27 +16,18 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/flattens"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenImage(d *schema.ResourceData, image *Image) {
@@ -77,16 +66,17 @@ func flattenImage(d *schema.ResourceData, image *Image) {
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
d.Set("meta", flattens.FlattenMeta(image.Meta))
d.Set("meta", flattenMeta(image.Meta))
d.Set("desc", image.Desc)
d.Set("shared_with", image.SharedWith)
return
}
func dataSourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
image, err := utilityImageCheckPresence(ctx, d, m)
func dataSourceImageRead(d *schema.ResourceData, m interface{}) error {
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(strconv.Itoa(image.Guid))
flattenImage(d, image)
@@ -306,15 +296,15 @@ func dataSourceImageSchemaMake() map[string]*schema.Schema {
}
}
func DataSourceImage() *schema.Resource {
func dataSourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceImageRead,
Read: dataSourceImageRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceImageSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,26 +16,17 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenImageList(il ImageList) []map[string]interface{} {
@@ -88,10 +77,10 @@ func flattenImageList(il ImageList) []map[string]interface{} {
return res
}
func dataSourceImageListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
imageList, err := utilityImageListCheckPresence(ctx, d, m)
func dataSourceImageListRead(d *schema.ResourceData, m interface{}) error {
imageList, err := utilityImageListCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
id := uuid.New()
d.SetId(id.String())
@@ -135,15 +124,15 @@ func dataSourceImageListSchemaMake() map[string]*schema.Schema {
return rets
}
func DataSourceImageList() *schema.Resource {
func dataSourceImageList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceImageListRead,
Read: dataSourceImageListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceImageListSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,29 +16,20 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenImageListStacks(_ *schema.ResourceData, stack ImageListStacks) []map[string]interface{} {
func flattenImageListStacks(d *schema.ResourceData, stack ImageListStacks) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range stack {
t := map[string]interface{}{
@@ -66,10 +55,10 @@ func flattenImageListStacks(_ *schema.ResourceData, stack ImageListStacks) []map
return temp
}
func dataSourceImageListStacksRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
imageListStacks, err := utilityImageListStacksCheckPresence(ctx, d, m)
func dataSourceImageListStacksRead(d *schema.ResourceData, m interface{}) error {
imageListStacks, err := utilityImageListStacksCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
id := uuid.New()
d.SetId(id.String())
@@ -177,15 +166,15 @@ func dataSourceImageListStacksSchemaMake() map[string]*schema.Schema {
}
}
func DataSourceImageListStacks() *schema.Resource {
func dataSourceImageListStacks() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceImageListStacksRead,
Read: dataSourceImageListStacksRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceImageListStacksSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,31 +16,24 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package rg
package decort
import (
"context"
"encoding/json"
"fmt"
"github.com/rudecs/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
// "net/url"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
@@ -70,8 +61,8 @@ func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
d.Set("def_net_type", details.DefaultNetType)
d.Set("def_net_id", details.DefaultNetID)
/*
d.Set("vins", details.Vins)
d.Set("computes", details.Computes)
d.Set("vins", details.Vins)
d.Set("computes", details.Computes)
*/
log.Debugf("flattenResgroup: calling flattenQuota()")
@@ -82,27 +73,27 @@ func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
return nil
}
func dataSourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
func dataSourceResgroupRead(d *schema.ResourceData, m interface{}) error {
rg_facts, err := utilityResgroupCheckPresence(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
d.SetId("") // ensure ID is empty in this case
return diag.FromErr(err)
return err
}
return diag.FromErr(flattenResgroup(d, rg_facts))
return flattenResgroup(d, rg_facts)
}
func DataSourceResgroup() *schema.Resource {
func dataSourceResgroup() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceResgroupRead,
Read: dataSourceResgroupRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
@@ -147,6 +138,7 @@ func DataSourceResgroup() *schema.Resource {
"quota": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(), // this is a dictionary
},
@@ -166,30 +158,30 @@ func DataSourceResgroup() *schema.Resource {
},
/*
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of 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,
MaxItems: LimitMaxVinsPerResgroup,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of VINs deployed in 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, //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, //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

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2020-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,53 +16,45 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package vins
package decort
import (
"context"
"encoding/json"
"fmt"
"github.com/rudecs/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
// "net/url"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
// vins_facts is a response string from API vins/get
func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
func flattenVins(d *schema.ResourceData, vins_facts string) error {
// 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)
if err != nil {
return diag.FromErr(err)
return err
}
log.Debugf("flattenVins: decoded ViNS name:ID %s:%d, account ID %d, RG ID %d",
vinsRecord.Name, vinsRecord.ID, vinsRecord.AccountID, vinsRecord.RgID)
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)
err = d.Set("rg_id", vinsRecord.RgID)
d.Set("description", vinsRecord.Desc)
d.Set("ipcidr", vinsRecord.IPCidr)
@@ -79,7 +69,7 @@ func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
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.")
return fmt.Errorf("Failed to unmarshal VNF GW Config - structure is invalid.")
}
noExtNetConnection = false
break
@@ -96,27 +86,27 @@ func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
return nil
}
func dataSourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
func dataSourceVinsRead(d *schema.ResourceData, m interface{}) error {
vinsFacts, err := utilityVinsCheckPresence(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)
return err
}
return flattenVins(d, vinsFacts)
}
func DataSourceVins() *schema.Resource {
func dataSourceVins() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceVinsRead,
Read: dataSourceVinsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
@@ -127,11 +117,11 @@ func DataSourceVins() *schema.Resource {
},
/*
"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.",
},
"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": {

View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
package decort
import (
// log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
// ID, type, name, size, account ID, SEP ID, SEP type, pool, status, tech status, compute ID, image ID
func diskSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of this disk.",
},
"size": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Size of the disk in GB.",
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "ID of the account this disk belongs to.",
},
"type": {
Type: schema.TypeString,
Optional: true,
Description: "Type of this disk.",
},
"sep_id": {
Type: schema.TypeString,
Optional: true,
Default: "default",
Description: "ID of the storage end-point provider serving this disk.",
},
"sep_type": {
Type: schema.TypeString,
Optional: true,
Default: "default",
Description: "Type of the storage provider serving this disk.",
},
"pool": {
Type: schema.TypeString,
Optional: true,
Default: "default",
Description: "Pool on the storage where this disk is located.",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the binary Image this disk resource is cloned from (if any).",
},
}
return rets
}

View File

@@ -0,0 +1,331 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file contains definitions and code for handling Interface component of Compute schema
*/
package decort
import (
/*
"log"
"strconv"
"strings"
*/
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func interfaceSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"net_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the network entity this interface is connected to.",
},
"net_type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of the network entity this interface is connected to.",
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
Description: "IP addresses assigned to this interface.",
},
"netmask": {
Type: schema.TypeInt,
Computed: true,
Description: "Network mask to be used with this interface.",
},
"mac": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address of this interface.",
},
"default_gw": {
Type: schema.TypeString,
Computed: true,
Description: "Default gateway associated with this interface.",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Interface name.",
},
"connection_id": {
Type: schema.TypeInt,
Computed: true,
Description: "VxLAN or VLAN ID this interface is connected to.",
},
"connection_type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of the segment (VLAN or VxLAN) this interface is connected to.",
},
"qos": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: interfaceQosSubresourceSchemaMake(),
},
Description: "QoS settings for this interface.",
},
}
return rets
}
func interfaceQosSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"egress_rate": {
Type: schema.TypeInt,
Computed: true,
Description: "Egress rate limit on this interface.",
},
"ingress_burst": {
Type: schema.TypeInt,
Computed: true,
Description: "Ingress burst limit on this interface.",
},
"ingress_rate": {
Type: schema.TypeInt,
Computed: true,
Description: "Ingress rate limit on this interface.",
},
"guid": {
Type: schema.TypeString,
Computed: true,
Description: "GUID of this QoS record.",
},
}
return rets
}
/*
func flattenNetworks(nets []NicRecord) []interface{} {
// this function expects an array of NicRecord as returned by machines/get API call
// NOTE: it does NOT expect a strucutre as returned by externalnetwork/list
var length = 0
var strarray []string
for _, value := range nets {
if value.NicType == "PUBLIC" {
length += 1
}
}
log.Debugf("flattenNetworks: found %d NICs with PUBLIC type", length)
result := make([]interface{}, length)
if length == 0 {
return result
}
elem := make(map[string]interface{})
var subindex = 0
for index, value := range nets {
if value.NicType == "PUBLIC" {
// this will be changed as network segments entity
// value.Params for ext net comes in a form "gateway:176.118.165.1 externalnetworkId:6"
// for network_id we need to extract from this string
strarray = strings.Split(value.Params, " ")
substr := strings.Split(strarray[1], ":")
elem["network_id"], _ = strconv.Atoi(substr[1])
elem["ip_range"] = value.IPAddress
// elem["label"] = ... - should be uncommented for the future release
log.Debugf("flattenNetworks: parsed element %d - network_id %d, ip_range %s",
index, elem["network_id"].(int), value.IPAddress)
result[subindex] = elem
subindex += 1
}
}
return result
}
func makePortforwardsConfig(arg_list []interface{}) (pfws []PortforwardConfig, count int) {
count = len(arg_list)
if count < 1 {
return nil, 0
}
pfws = make([]PortforwardConfig, count)
var subres_data map[string]interface{}
for index, value := range arg_list {
subres_data = value.(map[string]interface{})
// pfws[index].Label = subres_data["label"].(string) - should be uncommented for future release
pfws[index].ExtPort = subres_data["ext_port"].(int)
pfws[index].IntPort = subres_data["int_port"].(int)
pfws[index].Proto = subres_data["proto"].(string)
}
return pfws, count
}
func flattenPortforwards(pfws []PortforwardRecord) []interface{} {
result := make([]interface{}, len(pfws))
elem := make(map[string]interface{})
var port_num int
for index, value := range pfws {
// elem["label"] = ... - should be uncommented for the future release
// external port field is of TypeInt in the portforwardSubresourceSchema, but string is returned
// by portforwards/list API, so we need conversion here
port_num, _ = strconv.Atoi(value.ExtPort)
elem["ext_port"] = port_num
// internal port field is of TypeInt in the portforwardSubresourceSchema, but string is returned
// by portforwards/list API, so we need conversion here
port_num, _ = strconv.Atoi(value.IntPort)
elem["int_port"] = port_num
elem["proto"] = value.Proto
elem["ext_ip"] = value.ExtIP
elem["int_ip"] = value.IntIP
result[index] = elem
}
return result
}
func portforwardSubresourceSchema() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"label": {
Type: schema.TypeString,
Required: true,
Description: "Unique label of this network connection to identify it amnong other connections for this VM.",
},
"ext_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 65535),
Description: "External port number for this port forwarding rule.",
},
"int_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 65535),
Description: "Internal port number for this port forwarding rule.",
},
"proto": {
Type: schema.TypeString,
Required: true,
// ValidateFunc: validation.IntBetween(1, ),
Description: "Protocol type for this port forwarding rule. Should be either 'tcp' or 'udp'.",
},
"ext_ip": {
Type: schema.TypeString,
Computed: true,
Description: ".",
},
"int_ip": {
Type: schema.TypeString,
Computed: true,
Description: ".",
},
}
return rets
}
func flattenNICs(nics []NicRecord) []interface{} {
var result = make([]interface{}, len(nics))
elem := make(map[string]interface{})
for index, value := range nics {
elem["status"] = value.Status
elem["type"] = value.NicType
elem["mac"] = value.MacAddress
elem["ip_address"] = value.IPAddress
elem["parameters"] = value.Params
elem["reference_id"] = value.ReferenceID
elem["network_id"] = value.NetworkID
result[index] = elem
}
return result
}
func nicSubresourceSchema() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this NIC.",
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of this NIC.",
},
"mac": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address assigned to this NIC.",
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
Description: "IP address assigned to this NIC.",
},
"parameters": {
Type: schema.TypeString,
Computed: true,
Description: "Additional NIC parameters.",
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
Description: "Reference ID of this NIC.",
},
"network_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Network ID which this NIC is connected to.",
},
}
return rets
}
*/

801
decort/models_api.go Normal file
View File

@@ -0,0 +1,801 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
"strconv"
"time"
)
//
// timeouts for API calls from CRUD functions of Terraform plugin
var Timeout30s = time.Second * 30
var Timeout60s = time.Second * 60
var Timeout180s = time.Second * 180
var Timeout10m = time.Minute * 10
//
// structures related to /cloudapi/rg/list API
//
type UserAclRecord struct {
IsExplicit bool `json:"explicit"`
Rights string `json:"right"`
Status string `json:"status"`
Type string `json:"type"`
UgroupID string `json:"userGroupId"`
// CanBeDeleted bool `json:"canBeDeleted"`
}
type AccountAclRecord struct {
IsExplicit bool `json:"explicit"`
Guid string `json:"guid"`
Rights string `json:"right"`
Status string `json:"status"`
Type string `json:"type"`
UgroupID string `json:"userGroupId"`
}
type ResgroupRecord struct {
ACLs []UserAclRecord `json:"acl"`
Owner AccountAclRecord `json:"accountAcl"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
DefaultNetType string `json:"def_net_type"`
Decsription string `json:"desc"`
GridID int `json:"gid"`
ID uint `json:"id"`
LockStatus string `json:"lockStatus"`
Name string `json:"name"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"`
Vins []int `json:"vins"`
Computes []int `json:"vms"`
}
const ResgroupListAPI = "/restmachine/cloudapi/rg/list"
type ResgroupListResp []ResgroupRecord
//
// structures related to /cloudapi/rg/create API call
//
const ResgroupCreateAPI = "/restmachine/cloudapi/rg/create"
//
// structures related to /cloudapi/rg/update API call
//
const ResgroupUpdateAPI = "/restmachine/cloudapi/rg/update"
type ResgroupUpdateParam struct {
RgId int `json:"rgId"`
Name string `json:"name"`
Desc string `json:"decs"`
Ram int `json:"maxMemoryCapacity"`
Disk int `json:"maxVDiskCapacity"`
Cpu int `json:"maxCPUCapacity"`
NetTraffic int `json:"maxNetworkPeerTransfer"`
Reason string `json:"reason"`
}
//
// structures related to /cloudapi/rg/get API call
//
type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get
Cpu int `json:"CU_C"` // CPU count in pcs
Ram float64 `json:"CU_M"` // RAM volume in MB, it is STILL reported as FLOAT
Disk int `json:"CU_D"` // Disk capacity in GB
ExtIPs int `json:"CU_I"` // Ext IPs count
ExtTraffic int `json:"CU_NP"` // Ext network traffic
GpuUnits int `json:"gpu_units"` // GPU count
}
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"`
}
type UsageRecord struct {
Current ResourceRecord `json:"Current"`
Reserved ResourceRecord `json:"Reserved"`
}
const ResgroupGetAPI = "/restmachine/cloudapi/rg/get"
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"`
Ignored map[string]interface{} `json:"-"`
}
//
// structures related to /cloudapi/rg/delete API
//
const ResgroupDeleteAPI = "/restmachine/cloudapi/rg/delete"
//
// structures related to /cloudapi/rg/listComputes API
//
type ComputeBriefRecord struct { // this is a brief compute specifiaction as returned by API rg/listComputes
// we do not even include here all fields as returned by this API, but only the most important that
// are really necessary to identify and distinguish computes
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
Name string `json:"name"`
ID uint `json:"id"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
}
const RgListComputesAPI = "/restmachine/cloudapi/rg/listComputes"
type RgListComputesResp []ComputeBriefRecord
//
// structures related to /cloudapi/kvmXXX/create APIs
//
const KvmX86CreateAPI = "/restmachine/cloudapi/kvmx86/create"
const KvmPPCCreateAPI = "/restmachine/cloudapi/kvmppc/create"
type KvmVmCreateParam struct { // this is unified structure for both x86 and PPC based KVM VMs creation
RgID uint `json:"rgId"`
Name string `json:"name"`
Cpu int `json:"cpu"`
Ram int `json:"ram"`
ImageID int `json:"imageId"`
BootDisk int `json:"bootDisk"`
NetType string `json:"netType"`
NetId int `json:"netId"`
IPAddr string `json:"ipAddr"`
UserData string `json:"userdata"`
Desc string `json:"desc"`
Start bool `json:"start"`
}
// structures related to cloudapi/compute/start API
const ComputeStartAPI = "/restmachine/cloudapi/compute/start"
const ComputeStopAPI = "/restmachine/cloudapi/compute/stop"
// structures related to cloudapi/compute/delete API
const ComputeDeleteAPI = "/restmachine/cloudapi/compute/delete"
//
// structures related to /cloudapi/compute/list API
//
type InterfaceQosRecord struct {
ERate int `json:"eRate"`
Guid string `json:"guid"`
InBurst int `json:"inBurst"`
InRate int `json:"inRate"`
}
type InterfaceRecord struct {
ConnID int `json:"connId"` // This is VLAN ID or VxLAN ID, depending on ConnType
ConnType string `json:"connType"` // Either "VLAN" or "VXLAN" tag
DefaultGW string `json:"defGw"`
Guid string `json:"guid"`
IPAddress string `json:"ipAddress"` // without trailing network mask, i.e. "192.168.1.3"
MAC string `json:"mac"`
Name string `json:"name"`
NetID int `json:"netId"` // This is either ExtNet ID or ViNS ID, depending on NetType
NetMask int `json:"netMask"`
NetType string `json:"netType"` // Either "EXTNET" or "VINS" tag
PciSlot int `json:"pciSlot"`
Target string `json:"target"`
Type string `json:"type"`
VNFs []int `json:"vnfs"`
QOS InterfaceQosRecord `json:"qos"`
}
type SnapSetRecord struct {
Disks []int `json:"disks"`
Guid string `json:"guid"`
Label string `json:"label"`
TimeStamp uint64 `json:"timestamp"`
}
type ComputeRecord struct {
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
ACLs []UserAclRecord `json:"acl"`
Arch string `json:"arch"`
BootDiskSize int `json:"bootdiskSize"`
CloneReference int `json:"cloneReference"`
Clones []int `json:"clones"`
Cpus int `json:"cpus"`
CreatedBy string `json:"createdBy"`
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"`
DeletedTime uint64 `json:"deletedTime"`
Desc string `json:"desc"`
Disks []int `json:"disks"`
GridID int `json:"gid"`
ID uint `json:"id"`
ImageID int `json:"imageId"`
Interfaces []InterfaceRecord `json:"interfaces"`
LockStatus string `json:"lockStatus"`
ManagerID int `json:"managerId"`
Name string `json:"name"`
Ram int `json:"ram"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
SnapSets []SnapSetRecord `json:"snapSets"`
Status string `json:"status"`
// Tags []string `json:"tags"` // Tags were reworked since DECORT 3.7.1
TechStatus string `json:"techStatus"`
TotalDiskSize int `json:"totalDiskSize"`
UpdatedBy string `json:"updatedBy"`
UpdateTime uint64 `json:"updateTime"`
UserManaged bool `json:"userManaged"`
Vgpus []int `json:"vgpus"`
VinsConnected int `json:"vinsConnected"`
VirtualImageID int `json:"virtualImageId"`
}
const ComputeListAPI = "/restmachine/cloudapi/compute/list"
type ComputeListResp []ComputeRecord
const ComputeResizeAPI = "/restmachine/cloudapi/compute/resize"
//
// structures related to /cloudapi/compute/get
//
type SnapshotRecord struct {
Guid string `json:"guid"`
Label string `json:"label"`
SnapSetGuid string `json:"snapSetGuid"`
SnapSetTime uint64 `json:"snapSetTime"`
TimeStamp uint64 `json:"timestamp"`
}
type DiskRecord struct {
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
// was - Acl map[string]string `json:"acl"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"` // NOTE: absent from compute/get output
BootPartition int `json:"bootPartition"`
CreatedTime uint64 `json:"creationTime"`
DeletedTime uint64 `json:"deletionTime"`
Desc string `json:"desc"`
DestructionTime uint64 `json:"destructionTime"`
DiskPath string `json:"diskPath"`
GridID int `json:"gid"`
ID uint `json:"id"`
ImageID int `json:"imageId"`
Images []int `json:"images"`
// IOTune 'json:"iotune" - it is a dictionary
Name string `json:"name"`
// Order `json:"order"`
ParentId int `json:"parentId"`
PciSlot int `json:"pciSlot"`
// ResID string `json:"resId"`
// ResName string `json:"resName"`
// Params string `json:"params"`
Pool string `json:"pool"`
PurgeTime uint64 `json:"purgeTime"`
// Role string `json:"role"`
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
Snapshots []SnapshotRecord `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
ComputeID int `json:"vmid"`
}
type OsUserRecord struct {
Guid string `json:"guid"`
Login string `json:"login"`
Password string `json:"password"`
PubKey string `json:"pubkey"`
}
const ComputeGetAPI = "/restmachine/cloudapi/compute/get"
type ComputeGetResp struct {
// ACLs `json:"ACL"` - it is a dictionary, special parsing required
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
Arch string `json:"arch"`
BootDiskSize int `json:"bootdiskSize"`
CloneReference int `json:"cloneReference"`
Clones []int `json:"clones"`
Cpu int `json:"cpus"`
Desc string `json:"desc"`
Disks []DiskRecord `json:"disks"`
Driver string `json:"driver"`
GridID int `json:"gid"`
ID uint `json:"id"`
ImageID int `json:"imageId"`
ImageName string `json:"imageName"`
Interfaces []InterfaceRecord `json:"interfaces"`
LockStatus string `json:"lockStatus"`
ManagerID int `json:"managerId"`
ManagerType string `json:"manageType"`
Name string `json:"name"`
NatableVinsID int `json:"natableVinsId"`
NatableVinsIP string `json:"natableVinsIp"`
NatableVinsName string `json:"natableVinsName"`
NatableVinsNet string `json:"natableVinsNetwork"`
NatableVinsNetName string `json:"natableVinsNetworkName"`
OsUsers []OsUserRecord `json:"osUsers"`
Ram int `json:"ram"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
SnapSets []SnapSetRecord `json:"snapSets"`
Status string `json:"status"`
// Tags []string `json:"tags"` // Tags were reworked since DECORT 3.7.1
TechStatus string `json:"techStatus"`
TotalDiskSize int `json:"totalDiskSize"`
UpdatedBy string `json:"updatedBy"`
UpdateTime uint64 `json:"updateTime"`
UserManaged bool `json:"userManaged"`
Vgpus []int `json:"vgpus"`
VinsConnected int `json:"vinsConnected"`
VirtualImageID int `json:"virtualImageId"`
}
//
// structures related to /restmachine/cloudapi/image/list API
//
type ImageRecord struct {
AccountID uint `json:"accountId"`
Arch string `json:"architecture"`
BootType string `json:"bootType"`
IsBootable bool `json:"bootable"`
IsCdrom bool `json:"cdrom"`
Desc string `json:"desc"`
IsHotResize bool `json:"hotResize"`
ID uint `json:"id"`
Name string `json:"name"`
Pool string `json:"pool"`
SepID int `json:"sepId"`
Size int `json:"size"`
Status string `json:"status"`
Type string `json:"type"`
Username string `json:"username"`
IsVirtual bool `json:"virtual"`
}
const ImagesListAPI = "/restmachine/cloudapi/image/list"
type ImagesListResp []ImageRecord
//
// structures related to /cloudapi/extnet/list API
//
type ExtNetRecord struct {
Name string `json:"name"`
ID uint `json:"id"`
IPCIDR string `json:"ipcidr"`
}
const ExtNetListAPI = "/restmachine/cloudapi/extnet/list"
type ExtNetListResp []ExtNetRecord
//
// structures related to /cloudapi/account/list API
//
type AccountRecord struct {
// ACLs []UserAclRecord `json:"acl"`
// CreatedTime uint64 `json:"creationTime"`
// DeletedTime uint64 `json:"deletionTime"`
ID int `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
// UpdatedTime uint64 `json:"updateTime"`
}
const AccountsGetAPI = "/restmachine/cloudapi/account/get" // returns AccountRecord superset
const AccountsListAPI = "/restmachine/cloudapi/account/list" // returns list of abdridged info about accounts
type AccountsListResp []AccountRecord
//
// structures related to /cloudapi/portforwarding/list API
//
type PfwRecord struct {
ID int `json:"id"`
LocalIP string `json:"localIp"`
LocalPort int `json:"localPort"`
Protocol string `json:"protocol"`
PublicPortEnd int `json:"publicPortEnd"`
PublicPortStart int `json:"publicPortStart"`
ComputeID int `json:"vmId"`
}
const ComputePfwListAPI = "/restmachine/cloudapi/compute/pfwList"
type ComputePfwListResp []PfwRecord
const ComputePfwAddAPI = "/restmachine/cloudapi/compute/pfwAdd"
const ComputePfwDelAPI = "/restmachine/cloudapi/compute/pfwDel"
//
// structures related to /cloudapi/compute/net Attach/Detach API
//
type ComputeNetMgmtRecord struct { // used to "cache" network specs when preparing to manage compute networks
ID int
Type string
IPAddress string
MAC string
}
const ComputeNetAttachAPI = "/restmachine/cloudapi/compute/netAttach"
const ComputeNetDetachAPI = "/restmachine/cloudapi/compute/netDetach"
//
// structures related to /cloudapi/compute/disk Attach/Detach API
//
const ComputeDiskAttachAPI = "/restmachine/cloudapi/compute/diskAttach"
const ComputeDiskDetachAPI = "/restmachine/cloudapi/compute/diskDetach"
//
// structures related to /cloudapi/disks/create
//
const DisksCreateAPI = "/restmachine/cloudapi/disks/create"
//
// structures related to /cloudapi/disks/get
//
const DisksGetAPI = "/restmachine/cloudapi/disks/get" // Returns single DiskRecord on success
const DisksListAPI = "/restmachine/cloudapi/disks/list" // Returns list of DiskRecord on success
type DisksListResp []DiskRecord
//
// structures related to /cloudapi/disks/resize
//
const DisksResizeAPI = "/restmachine/cloudapi/disks/resize2"
//
// structures related to /cloudapi/disks/resize
//
const DisksRenameAPI = "/restmachine/cloudapi/disks/rename"
//
// structures related to /cloudapi/disks/delete
//
const DisksDeleteAPI = "/restmachine/cloudapi/disks/delete"
//
// ViNS structures
//
// this is the structure of the element in the list returned by vins/search API
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"`
}
const VinsSearchAPI = "/restmachine/cloudapi/vins/search"
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"`
}
const VinsGetAPI = "/restmachine/cloudapi/vins/get"
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"
//
// K8s structures
//
//K8sNodeRecord represents a worker/master group
type K8sNodeRecord struct {
ID int `json:"id"`
Name string `json:"name"`
Disk int `json:"disk"`
Cpu int `json:"cpu"`
Num int `json:"num"`
Ram int `json:"ram"`
DetailedInfo []struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"detailedInfo"`
}
//K8sRecord represents k8s instance
type K8sRecord struct {
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
CI int `json:"ciId"`
ID int `json:"id"`
Groups struct {
Masters K8sNodeRecord `json:"masters"`
Workers []K8sNodeRecord `json:"workers"`
} `json:"k8sGroups"`
Name string `json:"name"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
}
const K8sCreateAPI = "/restmachine/cloudapi/k8s/create"
const K8sGetAPI = "/restmachine/cloudapi/k8s/get"
const K8sUpdateAPI = "/restmachine/cloudapi/k8s/update"
const K8sDeleteAPI = "/restmachine/cloudapi/k8s/delete"
const K8sWgCreateAPI = "/restmachine/cloudapi/k8s/workersGroupAdd"
const K8sWgDeleteAPI = "/restmachine/cloudapi/k8s/workersGroupDelete"
const K8sWorkerAddAPI = "/restmachine/cloudapi/k8s/workerAdd"
const K8sWorkerDeleteAPI = "/restmachine/cloudapi/k8s/deleteWorkerFromGroup"
const K8sGetConfigAPI = "/restmachine/cloudapi/k8s/getConfig"
//Blasphemous workaround for parsing Result value
type TaskResult int
func (r *TaskResult) UnmarshalJSON(b []byte) error {
if b[0] == '"' {
b := b[1 : len(b)-1]
if len(b) == 0 {
*r = 0
return nil
}
n, err := strconv.Atoi(string(b))
if err != nil {
return err
}
*r = TaskResult(n)
} else if b[0] == '[' {
res := []interface{}{}
if err := json.Unmarshal(b, &res); err != nil {
return err
}
if n, ok := res[0].(float64); ok {
*r = TaskResult(n)
} else {
return fmt.Errorf("could not unmarshal %v into int", res[0])
}
}
return nil
}
//AsyncTask represents a long task completion status
type AsyncTask struct {
AuditID string `json:"auditId"`
Completed bool `json:"completed"`
Error string `json:"error"`
Log []string `json:"log"`
Result TaskResult `json:"result"`
Stage string `json:"stage"`
Status string `json:"status"`
UpdateTime uint64 `json:"updateTime"`
UpdatedTime uint64 `json:"updatedTime"`
}
const AsyncTaskGetAPI = "/restmachine/cloudapi/tasks/get"
//
// Grid ID structures
//
type LocationRecord struct {
GridID int `json:"gid"`
Id int `json:"id"`
LocationCode string `json:"locationCode"`
Name string `json:"name"`
Flag string `json:"flag"`
}
const LocationsListAPI = "/restmachine/cloudapi/locations/list" // Returns list of GridRecord on success
type LocationsListResp []LocationRecord
//
// Auxiliary structures
//
type SshKeyConfig struct {
User string
SshKey string
UserShell string
}
////////////////////
// IMAGE API //
////////////////////
const imageCreateAPI = "/restmachine/cloudbroker/image/createImage"
const imageSyncCreateAPI = "/restmachine/cloudbroker/image/syncCreateImage"
const imageCreateVirtualAPI = "/restmachine/cloudbroker/image/createVirtual"
const imageCreateCDROMAPI = "/restmachine/cloudbroker/image/createCDROMImage"
const imageListStacksApi = "/restmachine/cloudbroker/image/listStacks"
const imageGetAPI = "/restmachine/cloudbroker/image/get"
const imageListGetAPI = "/restmachine/cloudbroker/image/list"
const imageEditAPI = "/restmachine/cloudbroker/image/edit"
const imageDeleteAPI = "/restmachine/cloudbroker/image/delete"
const imageDeleteCDROMAPI = "/restmachine/cloudbroker/image/deleteCDROMImage"
const imageEnableAPI = "/restmachine/cloudbroker/image/enable"
const imageDisableAPI = "/restmachine/cloudbroker/image/disable"
const imageEditNameAPI = "/restmachine/cloudbroker/image/rename"
const imageLinkAPI = "/restmachine/cloudbroker/image/link"
const imageShareAPI = "/restmachine/cloudbroker/image/share"
const imageComputeciSetAPI = "/restmachine/cloudbroker/image/computeciSet"
const imageComputeciUnsetAPI = "/restmachine/cloudbroker/image/computeciUnset"
const imageUpdateNodesAPI = "/restmachine/cloudbroker/image/updateNodes"
const imageDeleteImagesAPI = "/restmachine/cloudbroker/image/deleteImages"
type History struct {
Guid string `json:"guid"`
Id int `json:"id"`
Timestamp int64 `json:"timestamp"`
}
type Image struct {
ImageId int `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
Gid int `json:"gid"`
Guid int `json:"guid"`
Boottype string `json:"bootType"`
Imagetype string `json:"type"`
Drivers []string `json:"drivers"`
Hotresize bool `json:"hotResize"`
Bootable bool `json:"bootable"`
Username string `json:"username"`
Password string `json:"password"`
AccountId int `json:"accountId"`
UsernameDL string `json:"usernameDL"`
PasswordDL string `json:"passwordDL"`
SepId int `json:"sepId"`
PoolName string `json:"pool"`
Architecture string `json:"architecture"`
UNCPath string `json:"UNCPath"`
LinkTo int `json:"linkTo"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Size int `json:"size"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
ComputeciId int `json:"computeciId"`
Milestones int `json:"milestones"`
ProviderName string `json:"provider_name"`
PurgeAttempts int `json:"purgeAttempts"`
ReferenceId string `json:"referenceId"`
ResId string `json:"resId"`
ResName string `json:"resName"`
Rescuecd bool `json:"rescuecd"`
Meta []interface{} `json:"_meta"`
History []History `json:"history"`
LastModified int64 `json:"lastModified"`
Desc string `json:"desc"`
SharedWith []int `json:"sharedWith"`
}
type ImageList []Image
type ImageStack struct {
ApiURL string `json:"apiUrl"`
ApiKey string `json:"apikey"`
AppId string `json:"appId"`
Desc string `json:"desc"`
Drivers []string `json:"drivers"`
Error int `json:"error"`
Guid int `json:"guid"`
Id int `json:"id"`
Images []int `json:"images"`
Login string `json:"login"`
Name string `json:"name"`
Passwd string `json:"passwd"`
ReferenceId string `json:"referenceId"`
Status string `json:"status"`
Type string `json:"type"`
}
type ImageListStacks []ImageStack
/////////////////
// GRID API //
/////////////////
const GridListGetAPI = "/restmachine/cloudbroker/grid/list"
const GridGetAPI = "/restmachine/cloudbroker/grid/get"
type Grid struct {
Flag string `json:"flag"`
Gid int `json:"gid"`
Guid int `json:"guid"`
Id int `json:"id"`
LocationCode string `json:"locationCode"`
Name string `json:"name"`
}
type GridList []Grid

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,31 +15,21 @@ 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 kvmvm
package decort
import (
// "encoding/json"
// "fmt"
"bytes"
"hash/fnv"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
log "github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
// "net/url"
"sort"
"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/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
// "github.com/hashicorp/terraform-plugin-sdk/v2/internal/helper/hashcode"
)
// This is subresource of compute resource used when creating/managing compute network connections
@@ -55,19 +43,19 @@ func networkSubresIPAddreDiffSupperss(key, oldVal, newVal string, d *schema.Reso
return true // suppress difference
}
// This function is based on the original Terraform SerializeResourceForHash found
// This function is based on the original Terraform SerializeResourceForHash found
// in helper/schema/serialize.go
// It skips network subresource attributes, which are irrelevant for identification
// It skips network subresource attributes, which are irrelevant for identification
// of unique network blocks
func networkSubresourceSerialize(output *bytes.Buffer, val interface{}, resource *schema.Resource) {
if val == nil {
return
}
rs := resource.Schema
m := val.(map[string]interface{})
keys := make([]string, 0, len(rs))
var keys []string
allComputed := true
for k, val := range rs {
@@ -108,7 +96,7 @@ func networkSubresourceSerialize(output *bytes.Buffer, val interface{}, resource
// from network subresource (e.g. in flattenCompute)
//
// This function is based on the original Terraform function HashResource from
// helper/schema/set.go
// helper/schema/set.go
func HashNetworkSubresource(resource *schema.Resource) schema.SchemaSetFunc {
return func(v interface{}) int {
var serialized bytes.Buffer
@@ -123,11 +111,11 @@ func HashNetworkSubresource(resource *schema.Resource) schema.SchemaSetFunc {
func networkSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"net_type": {
Type: schema.TypeString,
Required: true,
StateFunc: statefuncs.StateFuncToUpper,
Type: schema.TypeString,
Required: true,
StateFunc: stateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"EXTNET", "VINS"}, false), // observe case while validating
Description: "Type of the network for this connection, either EXTNET or VINS.",
Description: "Type of the network for this connection, either EXTNET or VINS.",
},
"net_id": {
@@ -137,11 +125,11 @@ func networkSubresourceSchemaMake() map[string]*schema.Schema {
},
"ip_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Type: schema.TypeString,
Optional: true,
Computed: true,
DiffSuppressFunc: networkSubresIPAddreDiffSupperss,
Description: "Optional IP address to assign to this connection. This IP should belong to the selected network and free for use.",
Description: "Optional IP address to assign to this connection. This IP should belong to the selected network and free for use.",
},
"mac": {
@@ -149,6 +137,7 @@ func networkSubresourceSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "MAC address associated with this connection. MAC address is assigned automatically.",
},
}
return rets
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,20 +16,15 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package k8s
package decort
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
import "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
func nodeMasterDefault() K8sNodeRecord {
return K8sNodeRecord{
@@ -65,6 +58,7 @@ func parseNode(nodeList []interface{}) K8sNodeRecord {
func nodeToResource(node K8sNodeRecord) []interface{} {
mp := make(map[string]interface{})
mp["id"] = node.ID
mp["num"] = node.Num
mp["cpu"] = node.Cpu
mp["ram"] = node.Ram

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,24 +15,13 @@ 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 kvmvm
package decort
import (
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func parseOsUsers(logins []OsUserRecord) []interface{} {

View File

@@ -1,128 +1,157 @@
/*
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.
*/
package provider
import (
"fmt"
"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"
"golang.org/x/net/context"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/location"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
)
func Provider() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"authenticator": {
Type: schema.TypeString,
Required: true,
StateFunc: statefuncs.StateFuncToLower,
ValidateFunc: validation.StringInSlice([]string{"oauth2", "legacy", "jwt"}, true), // ignore case while validating
Description: "Authentication mode to use when connecting to DECORT cloud API. Should be one of 'oauth2', 'legacy' or 'jwt'.",
},
"oauth2_url": {
Type: schema.TypeString,
Optional: true,
StateFunc: statefuncs.StateFuncToLower,
DefaultFunc: schema.EnvDefaultFunc("DECORT_OAUTH2_URL", nil),
Description: "OAuth2 application URL in 'oauth2' authentication mode.",
},
"controller_url": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: statefuncs.StateFuncToLower,
Description: "URL of DECORT Cloud controller to use. API calls will be directed to this URL.",
},
"user": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_USER", nil),
Description: "User name for DECORT cloud API operations in 'legacy' authentication mode.",
},
"password": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_PASSWORD", nil),
Description: "User password for DECORT cloud API operations in 'legacy' authentication mode.",
},
"app_id": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_APP_ID", nil),
Description: "Application ID to access DECORT cloud API in 'oauth2' authentication mode.",
},
"app_secret": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_APP_SECRET", nil),
Description: "Application secret to access DECORT cloud API in 'oauth2' authentication mode.",
},
"jwt": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_JWT", nil),
Description: "JWT to access DECORT cloud API in 'jwt' authentication mode.",
},
"allow_unverified_ssl": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "If true, DECORT API will not verify SSL certificates. Use this with caution and in trusted environments only!",
},
},
ResourcesMap: selectSchema(false),
DataSourcesMap: selectSchema(true),
ConfigureContextFunc: providerConfigure,
}
}
func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
decsController, err := controller.ControllerConfigure(d)
if err != nil {
return nil, diag.FromErr(err)
}
gridId, err := location.UtilityLocationGetDefaultGridID(ctx, decsController)
if err != nil {
return nil, diag.FromErr(err)
}
if gridId == 0 {
return nil, diag.FromErr(fmt.Errorf("providerConfigure: invalid default Grid ID = 0"))
}
return decsController, nil
}
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
package decort
import (
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
// "github.com/hashicorp/terraform-plugin-sdk/terraform"
)
var decsController *ControllerCfg
func Provider() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"authenticator": {
Type: schema.TypeString,
Required: true,
StateFunc: stateFuncToLower,
ValidateFunc: validation.StringInSlice([]string{"oauth2", "legacy", "jwt"}, true), // ignore case while validating
Description: "Authentication mode to use when connecting to DECORT cloud API. Should be one of 'oauth2', 'legacy' or 'jwt'.",
},
"oauth2_url": {
Type: schema.TypeString,
Optional: true,
StateFunc: stateFuncToLower,
DefaultFunc: schema.EnvDefaultFunc("DECORT_OAUTH2_URL", nil),
Description: "OAuth2 application URL in 'oauth2' authentication mode.",
},
"controller_url": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: stateFuncToLower,
Description: "URL of DECORT Cloud controller to use. API calls will be directed to this URL.",
},
"user": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_USER", nil),
Description: "User name for DECORT cloud API operations in 'legacy' authentication mode.",
},
"password": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_PASSWORD", nil),
Description: "User password for DECORT cloud API operations in 'legacy' authentication mode.",
},
"app_id": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_APP_ID", nil),
Description: "Application ID to access DECORT cloud API in 'oauth2' authentication mode.",
},
"app_secret": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_APP_SECRET", nil),
Description: "Application secret to access DECORT cloud API in 'oauth2' authentication mode.",
},
"jwt": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DECORT_JWT", nil),
Description: "JWT to access DECORT cloud API in 'jwt' authentication mode.",
},
"allow_unverified_ssl": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "If true, DECORT API will not verify SSL certificates. Use this with caution and in trusted environments only!",
},
},
ResourcesMap: map[string]*schema.Resource{
"decort_resgroup": resourceResgroup(),
"decort_kvmvm": resourceCompute(),
"decort_disk": resourceDisk(),
"decort_vins": resourceVins(),
"decort_pfw": resourcePfw(),
"decort_k8s": resourceK8s(),
"decort_k8s_wg": resourceK8sWg(),
"decort_image": resourceImage(),
"decort_virtual_image": resourceVirtualImage(),
"decort_cdrom_image": resourceCDROMImage(),
"decort_delete_images": resourceDeleteImages(),
},
DataSourcesMap: map[string]*schema.Resource{
"decort_account": dataSourceAccount(),
"decort_resgroup": dataSourceResgroup(),
"decort_kvmvm": dataSourceCompute(),
"decort_image": dataSourceImage(),
"decort_disk": dataSourceDisk(),
"decort_vins": dataSourceVins(),
"decort_grid": dataSourceGrid(),
"decort_grid_list": dataSourceGridList(),
"decort_image_list": dataSourceImageList(),
"decort_image_list_stacks": dataSourceImageListStacks(),
// "decort_pfw": dataSourcePfw(),
},
ConfigureFunc: providerConfigure,
}
}
func stateFuncToLower(argval interface{}) string {
return strings.ToLower(argval.(string))
}
func stateFuncToUpper(argval interface{}) string {
return strings.ToUpper(argval.(string))
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
decsController, err := ControllerConfigure(d)
if err != nil {
return nil, err
}
// initialize global default Grid ID - it will be needed to create some resource types, e.g. disks
gridId, err := decsController.utilityLocationGetDefaultGridID()
if err != nil {
return nil, err
}
if gridId == 0 {
return nil, fmt.Errorf("providerConfigure: invalid default Grid ID = 0")
}
return decsController, nil
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,25 +15,20 @@ 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
package decort
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
// "encoding/json"
// "fmt"
// "log"
// "net/url"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
func makeQuotaRecord(arg_list []interface{}) (QuotaRecord, int) {
quota := QuotaRecord{
Cpu: -1,
Ram: -1., // this is float64, but may change in the future
@@ -70,7 +63,7 @@ func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
quota.GpuUnits = subres_data["gpu_units"].(int)
}
return quota
return quota, 1
}
func parseQuota(quota QuotaRecord) []interface{} {

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: 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.
@@ -18,35 +16,27 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"net/url"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceCDROMImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceCDROMImageCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceCDROMImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("url", d.Get("url").(string))
@@ -90,43 +80,43 @@ func resourceCDROMImageCreate(ctx context.Context, d *schema.ResourceData, m int
urlValues.Add("architecture", architecture.(string))
}
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateCDROMAPI, urlValues)
imageId, err := controller.decortAPICall("POST", imageCreateCDROMAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(imageId)
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceCDROMImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceCDROMImageDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceCDROMImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if image == nil {
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
@@ -134,9 +124,9 @@ func resourceCDROMImageDelete(ctx context.Context, d *schema.ResourceData, m int
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
_, err = c.DecortAPICall(ctx, "POST", imageDeleteCDROMAPI, urlValues)
_, err = controller.decortAPICall("POST", imageDeleteCDROMAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId("")
@@ -371,27 +361,89 @@ func resourceCDROMImageSchemaMake() map[string]*schema.Schema {
}
}
func ResourceCDROMImage() *schema.Resource {
func resourceCDROMImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceCDROMImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
DeleteContext: resourceCDROMImageDelete,
Create: resourceCDROMImageCreate,
Read: resourceImageRead,
Update: resourceImageEdit,
Delete: resourceCDROMImageDelete,
Exists: resourceImageExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout60s,
Read: &constants.Timeout30s,
Update: &constants.Timeout60s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName),
customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageUpdateNodes),
),
Schema: resourceCDROMImageSchemaMake(),
}
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,33 +16,24 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package kvmvm
package decort
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
log "github.com/sirupsen/logrus"
"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/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func cloudInitDiffSupperss(key, oldVal, newVal string, d *schema.ResourceData) bool {
@@ -60,7 +49,7 @@ func cloudInitDiffSupperss(key, oldVal, newVal string, d *schema.ResourceData) b
return true // suppress difference
}
func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceComputeCreate(d *schema.ResourceData, m interface{}) error {
// we assume all mandatory parameters it takes to create a comptue instance are properly
// specified - we rely on schema "Required" attributes to let Terraform validate them for us
@@ -68,7 +57,9 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
// create basic Compute (i.e. without extra disks and network connections - those will be attached
// by subsequent individual API calls).
c := m.(*controller.ControllerCfg)
// creating Compute is a multi-step workflow, which may fail at some step, so we use "partial" feature of Terraform
d.Partial(true)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("rgId", fmt.Sprintf("%d", d.Get("rg_id").(int)))
urlValues.Add("name", d.Get("name").(string))
@@ -84,14 +75,6 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
urlValues.Add("desc", argVal.(string))
}
if sepID, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepID.(int)))
}
if pool, ok := d.GetOk("pool"); ok {
urlValues.Add("pool", pool.(string))
}
/*
sshKeysVal, sshKeysSet := d.GetOk("ssh_keys")
if sshKeysSet {
@@ -119,55 +102,64 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
}
}
apiResp, err := c.DecortAPICall(ctx, "POST", computeCreateAPI, urlValues)
apiResp, err := controller.decortAPICall("POST", computeCreateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
// Compute create API returns ID of the new Compute instance on success
d.SetId(apiResp) // update ID of the resource to tell Terraform that the resource exists, albeit partially
compId, _ := strconv.Atoi(apiResp)
cleanup := false
defer func() {
if cleanup {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("permanently", "1")
urlValues.Add("detachDisks", "1")
if _, err := c.DecortAPICall(ctx, "POST", ComputeDeleteAPI, urlValues); err != nil {
log.Errorf("resourceComputeCreate: could not delete compute after failed creation: %v", err)
}
d.SetId("")
d.SetPartial("name")
d.SetPartial("description")
d.SetPartial("cpu")
d.SetPartial("ram")
d.SetPartial("image_id")
d.SetPartial("boot_disk_size")
/*
if sshKeysSet {
d.SetPartial("ssh_keys")
}
}()
*/
log.Debugf("resourceComputeCreate: new simple Compute ID %d, name %s created", compId, d.Get("name").(string))
// Configure data disks if any
extraDisksOk := true
argVal, argSet = d.GetOk("extra_disks")
if argSet && argVal.(*schema.Set).Len() > 0 {
// urlValues.Add("desc", argVal.(string))
log.Debugf("resourceComputeCreate: calling utilityComputeExtraDisksConfigure to attach %d extra disk(s)", argVal.(*schema.Set).Len())
err = utilityComputeExtraDisksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
err = controller.utilityComputeExtraDisksConfigure(d, false) // do_delta=false, as we are working on a new compute
if err != nil {
log.Errorf("resourceComputeCreate: error when attaching extra disk(s) to a new Compute ID %d: %v", compId, err)
cleanup = true
return diag.FromErr(err)
log.Errorf("resourceComputeCreate: error when attaching extra disk(s) to a new Compute ID %s: %s", compId, err)
extraDisksOk = false
}
}
if extraDisksOk {
d.SetPartial("extra_disks")
}
// Configure external networks if any
netsOk := true
argVal, argSet = d.GetOk("network")
if argSet && argVal.(*schema.Set).Len() > 0 {
log.Debugf("resourceComputeCreate: calling utilityComputeNetworksConfigure to attach %d network(s)", argVal.(*schema.Set).Len())
err = utilityComputeNetworksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
err = controller.utilityComputeNetworksConfigure(d, false) // do_delta=false, as we are working on a new compute
if err != nil {
log.Errorf("resourceComputeCreate: error when attaching networks to a new Compute ID %d: %s", compId, err)
cleanup = true
return diag.FromErr(err)
netsOk = false
}
}
if netsOk {
// there were no errors reported when configuring networks
d.SetPartial("network")
}
if extraDisksOk && netsOk {
// if there were no errors in setting any of the subresources, we may leave Partial mode
d.Partial(false)
}
// Note bene: we created compute in a STOPPED state (this is required to properly attach 1st network interface),
// now we need to start it before we report the sequence complete
@@ -175,9 +167,9 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
reqValues := &url.Values{}
reqValues.Add("computeId", fmt.Sprintf("%d", compId))
log.Debugf("resourceComputeCreate: starting Compute ID %d after completing its resource configuration", compId)
if _, err := c.DecortAPICall(ctx, "POST", ComputeStartAPI, reqValues); err != nil {
cleanup = true
return diag.FromErr(err)
apiResp, err = controller.decortAPICall("POST", ComputeStartAPI, reqValues)
if err != nil {
return err
}
}
@@ -187,24 +179,24 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
// between Compute resource and Compute data source schemas
// Compute read function will also update resource ID on success, so that Terraform
// will know the resource exists
return dataSourceComputeRead(ctx, d, m)
return dataSourceComputeRead(d, m)
}
func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceComputeRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceComputeRead: called for Compute name %s, RG ID %d",
d.Get("name").(string), d.Get("rg_id").(int))
compFacts, err := utilityComputeCheckPresence(ctx, d, m)
compFacts, err := utilityComputeCheckPresence(d, m)
if compFacts == "" {
if err != nil {
return diag.FromErr(err)
return err
}
// Compute with such name and RG ID was not found
return nil
}
if err = flattenCompute(d, compFacts); err != nil {
return diag.FromErr(err)
return err
}
log.Debugf("resourceComputeRead: after flattenCompute: Compute ID %s, name %q, RG ID %d",
@@ -213,11 +205,11 @@ func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interfac
return nil
}
func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceComputeUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceComputeUpdate: called for Compute ID %s / name %s, RGID %d",
d.Id(), d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
/*
1. Resize CPU/RAM
@@ -232,6 +224,8 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
doUpdate := false
params.Add("computeId", d.Id())
d.Partial(true)
oldCpu, newCpu := d.GetChange("cpu")
if oldCpu.(int) != newCpu.(int) {
params.Add("cpu", fmt.Sprintf("%d", newCpu.(int)))
@@ -252,11 +246,12 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
log.Debugf("resourceComputeUpdate: changing CPU %d -> %d and/or RAM %d -> %d",
oldCpu.(int), newCpu.(int),
oldRam.(int), newRam.(int))
params.Add("force", "true")
_, err := c.DecortAPICall(ctx, "POST", ComputeResizeAPI, params)
_, err := controller.decortAPICall("POST", ComputeResizeAPI, params)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetPartial("cpu")
d.SetPartial("ram")
}
// 2. Resize (grow) Boot disk
@@ -267,46 +262,54 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
bdsParams.Add("size", fmt.Sprintf("%d", newSize.(int)))
log.Debugf("resourceComputeUpdate: compute ID %s, boot disk ID %d resize %d -> %d",
d.Id(), d.Get("boot_disk_id").(int), oldSize.(int), newSize.(int))
_, err := c.DecortAPICall(ctx, "POST", DisksResizeAPI, bdsParams)
_, err := controller.decortAPICall("POST", DisksResizeAPI, params)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetPartial("boot_disk_size")
} else if oldSize.(int) > newSize.(int) {
log.Warnf("resourceComputeUpdate: compute ID %s - shrinking boot disk is not allowed", d.Id())
log.Warnf("resourceComputeUpdate: compute ID %d - shrinking boot disk is not allowed", d.Id())
}
// 3. Calculate and apply changes to data disks
err := utilityComputeExtraDisksConfigure(ctx, d, m, true) // pass do_delta = true to apply changes, if any
err := controller.utilityComputeExtraDisksConfigure(d, true) // pass do_delta = true to apply changes, if any
if err != nil {
return diag.FromErr(err)
return err
} else {
d.SetPartial("extra_disks")
}
// 4. Calculate and apply changes to network connections
err = utilityComputeNetworksConfigure(ctx, d, m, true) // pass do_delta = true to apply changes, if any
err = controller.utilityComputeNetworksConfigure(d, true) // pass do_delta = true to apply changes, if any
if err != nil {
return diag.FromErr(err)
return err
} else {
d.SetPartial("network")
}
if d.HasChange("started") {
params := &url.Values{}
params.Add("computeId", d.Id())
if d.Get("started").(bool) {
if _, err := c.DecortAPICall(ctx, "POST", ComputeStartAPI, params); err != nil {
return diag.FromErr(err)
if _, err := controller.decortAPICall("POST", ComputeStartAPI, params); err != nil {
return err
}
} else {
if _, err := c.DecortAPICall(ctx, "POST", ComputeStopAPI, params); err != nil {
return diag.FromErr(err)
if _, err := controller.decortAPICall("POST", ComputeStopAPI, params); err != nil {
return err
}
}
d.SetPartial("started")
}
d.Partial(false)
// we may reuse dataSourceComputeRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return dataSourceComputeRead(ctx, d, m)
return dataSourceComputeRead(d, m)
}
func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceComputeDelete(d *schema.ResourceData, m interface{}) error {
// NOTE: this function destroys target Compute instance "permanently", so
// there is no way to restore it.
// If compute being destroyed has some extra disks attached, they are
@@ -314,39 +317,89 @@ func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interf
log.Debugf("resourceComputeDelete: called for Compute name %s, RG ID %d",
d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
compFacts, err := utilityComputeCheckPresence(d, m)
if compFacts == "" {
// the target Compute does not exist - in this case according to Terraform best practice
// we exit from Destroy method without error
return nil
}
controller := m.(*ControllerCfg)
model := ComputeGetResp{}
log.Debugf("resourceComputeDelete: ready to unmarshal string %s", compFacts)
err = json.Unmarshal([]byte(compFacts), &model)
if err == nil && len(model.Disks) > 0 {
// prepare to detach data disks from compute - do it only if compFacts unmarshalled
// properly and the resulting model contains non-empty Disks list
for _, diskFacts := range model.Disks {
if diskFacts.Type == "B" {
// boot disk is never detached on compute delete
continue
}
log.Debugf("resourceComputeDelete: ready to detach data disk ID %d from compute ID %s", diskFacts.ID, d.Id())
detachParams := &url.Values{}
detachParams.Add("computeId", d.Id())
detachParams.Add("diskId", fmt.Sprintf("%d", diskFacts.ID))
_, err = controller.decortAPICall("POST", ComputeDiskDetachAPI, detachParams)
if err != nil {
// We do not fail compute deletion on data disk detach errors
log.Errorf("resourceComputeDelete: error when detaching Disk ID %d: %s", diskFacts.ID, err)
}
}
}
params := &url.Values{}
params.Add("computeId", d.Id())
params.Add("permanently", "1")
params.Add("detachDisks", "1")
// TODO: this is for the upcoming API update - params.Add("detachdisks", "1")
if _, err := c.DecortAPICall(ctx, "POST", ComputeDeleteAPI, params); err != nil {
return diag.FromErr(err)
_, err = controller.decortAPICall("POST", ComputeDeleteAPI, params)
if err != nil {
return err
}
return nil
}
func ResourceCompute() *schema.Resource {
func resourceComputeExists(d *schema.ResourceData, m interface{}) (bool, error) {
// Reminder: according to Terraform rules, this function should not modify its ResourceData argument
log.Debugf("resourceComputeExist: called for Compute name %s, RG ID %d",
d.Get("name").(string), d.Get("rg_id").(int))
compFacts, err := utilityComputeCheckPresence(d, m)
if compFacts == "" {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceComputeCreate,
ReadContext: resourceComputeRead,
UpdateContext: resourceComputeUpdate,
DeleteContext: resourceComputeDelete,
Create: resourceComputeCreate,
Read: resourceComputeRead,
Update: resourceComputeUpdate,
Delete: resourceComputeDelete,
Exists: resourceComputeExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout180s,
Read: &constants.Timeout30s,
Update: &constants.Timeout180s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout180s,
Read: &Timeout30s,
Update: &Timeout180s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
@@ -367,7 +420,7 @@ func ResourceCompute() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: statefuncs.StateFuncToUpper,
StateFunc: stateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"KVM_X86", "KVM_PPC"}, false), // observe case while validating
Description: "Hardware architecture of this compute instance.",
},
@@ -375,22 +428,23 @@ func ResourceCompute() *schema.Resource {
"cpu": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, constants.MaxCpusPerCompute),
ValidateFunc: validation.IntBetween(1, MaxCpusPerCompute),
Description: "Number of CPUs to allocate to this compute instance.",
},
"ram": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(constants.MinRamPerCompute),
ValidateFunc: validation.IntAtLeast(MinRamPerCompute),
Description: "Amount of RAM in MB to allocate to this compute instance.",
},
"image_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "ID of the OS image to base this compute instance on.",
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "ID of the OS image to base this compute instance on.",
},
"boot_disk_size": {
@@ -399,26 +453,10 @@ func ResourceCompute() *schema.Resource {
Description: "This compute instance boot disk size in GB. Make sure it is large enough to accomodate selected OS image.",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
Description: "ID of SEP to create bootDisk on. Uses image's sepId if not set.",
},
"pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
Description: "Pool to use if sepId is set, can be also empty if needed to be chosen by system.",
},
"extra_disks": {
Type: schema.TypeSet,
Optional: true,
MaxItems: constants.MaxExtraDisksPerCompute,
MaxItems: MaxExtraDisksPerCompute,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
@@ -428,7 +466,7 @@ func ResourceCompute() *schema.Resource {
"network": {
Type: schema.TypeSet,
Optional: true,
MaxItems: constants.MaxNetworksPerCompute,
MaxItems: MaxNetworksPerCompute,
Elem: &schema.Resource{
Schema: networkSubresourceSchemaMake(),
},
@@ -501,6 +539,39 @@ func ResourceCompute() *schema.Resource {
Default: true,
Description: "Is compute started.",
},
/*
"disks": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: dataSourceDiskSchemaMake(), // ID, type, name, size, account ID, SEP ID, SEP type, pool, status, tech status, compute ID, image ID
},
Description: "Detailed specification for all disks attached to this compute instance (including bood disk).",
},
"interfaces": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: interfaceSubresourceSchemaMake(),
},
Description: "Specification for the virtual NICs configured on this compute instance.",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current model status of this compute instance.",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "Current technical status of this compute instance.",
},
*/
},
}
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: 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.
@@ -18,42 +16,33 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"net/url"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceCreateListImages(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceCreateListImages(d *schema.ResourceData, m interface{}) error {
id := uuid.New()
d.SetId(id.String())
return nil
}
func resourceDeleteListImages(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceDeleteListImages(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceDeleteListImages: start deleting...")
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
imageIds := d.Get("image_ids").([]interface{})
@@ -74,9 +63,9 @@ func resourceDeleteListImages(ctx context.Context, d *schema.ResourceData, m int
urlValues.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
urlValues.Add("imageIds", temp)
_, err := c.DecortAPICall(ctx, "POST", imageDeleteImagesAPI, urlValues)
_, err := c.decortAPICall("POST", imageDeleteImagesAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId("")
@@ -84,7 +73,7 @@ func resourceDeleteListImages(ctx context.Context, d *schema.ResourceData, m int
return nil
}
func resourceReadListImages(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceReadListImages(d *schema.ResourceData, m interface{}) error {
return nil
}
@@ -117,24 +106,24 @@ func resourceDeleteImagesSchemaMake() map[string]*schema.Schema {
}
func ResourceDeleteImages() *schema.Resource {
func resourceDeleteImages() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceCreateListImages,
ReadContext: resourceReadListImages,
DeleteContext: resourceDeleteListImages,
Create: resourceCreateListImages,
Read: resourceReadListImages,
Delete: resourceDeleteListImages,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout60s,
Read: &constants.Timeout30s,
Update: &constants.Timeout60s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceDeleteImagesSchemaMake(),

323
decort/resource_disk.go Normal file
View File

@@ -0,0 +1,323 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
// "encoding/json"
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func resourceDiskCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceDiskCreate: called for Disk name %q, Account ID %d", d.Get("name").(string), d.Get("account_id").(int))
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
// accountId, gid, name, description, size, type, sep_id, pool
urlValues.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
urlValues.Add("gid", fmt.Sprintf("%d", DefaultGridID)) // we use default Grid ID, which was obtained along with DECORT Controller init
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("size", fmt.Sprintf("%d", d.Get("size").(int)))
urlValues.Add("type", "D") // NOTE: only disks of Data type are managed via plugin
urlValues.Add("sep_id", fmt.Sprintf("%d", d.Get("sep_id").(int)))
urlValues.Add("pool", d.Get("pool").(string))
argVal, argSet := d.GetOk("description")
if argSet {
urlValues.Add("description", argVal.(string))
}
apiResp, err := controller.decortAPICall("POST", DisksCreateAPI, urlValues)
if err != nil {
return err
}
d.SetId(apiResp) // update ID of the resource to tell Terraform that the disk resource exists
diskId, _ := strconv.Atoi(apiResp)
log.Debugf("resourceDiskCreate: new Disk ID / name %d / %s creation sequence complete", diskId, d.Get("name").(string))
// We may reuse dataSourceDiskRead here as we maintain similarity
// between Disk resource and Disk data source schemas
// Disk 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 dataSourceDiskRead(d, m)
}
func resourceDiskRead(d *schema.ResourceData, m interface{}) error {
diskFacts, err := utilityDiskCheckPresence(d, m)
if diskFacts == "" {
// if empty string is returned from utilityDiskCheckPresence then there is no
// such Disk and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
return err
}
return flattenDisk(d, diskFacts)
}
func resourceDiskUpdate(d *schema.ResourceData, m interface{}) error {
// Update will only change the following attributes of the disk:
// - Size; to keep data safe, shrinking disk is not allowed.
// - Name
//
// Attempt to change disk type will throw an error and mark disk
// resource as partially updated
log.Debugf("resourceDiskUpdate: called for Disk ID / name %s / %s, Account ID %d",
d.Id(), d.Get("name").(string), d.Get("account_id").(int))
d.Partial(true)
controller := m.(*ControllerCfg)
oldSize, newSize := d.GetChange("size")
if oldSize.(int) < newSize.(int) {
log.Debugf("resourceDiskUpdate: resizing disk ID %s - %d GB -> %d GB",
d.Id(), oldSize.(int), newSize.(int))
sizeParams := &url.Values{}
sizeParams.Add("diskId", d.Id())
sizeParams.Add("size", fmt.Sprintf("%d", newSize.(int)))
_, err := controller.decortAPICall("POST", DisksResizeAPI, sizeParams)
if err != nil {
return err
}
d.SetPartial("size")
} else if oldSize.(int) > newSize.(int) {
return fmt.Errorf("resourceDiskUpdate: Disk ID %s - reducing disk size is not allowed", d.Id())
}
oldName, newName := d.GetChange("name")
if oldName.(string) != newName.(string) {
log.Debugf("resourceDiskUpdate: renaming disk ID %d - %s -> %s",
d.Get("disk_id").(int), oldName.(string), newName.(string))
renameParams := &url.Values{}
renameParams.Add("diskId", d.Id())
renameParams.Add("name", newName.(string))
_, err := controller.decortAPICall("POST", DisksRenameAPI, renameParams)
if err != nil {
return err
}
d.SetPartial("name")
}
/*
NOTE: plugin will manage disks of type "Data" only, and type cannot be changed once disk is created
oldType, newType := d.GetChange("type")
if oldType.(string) != newType.(string) {
return fmt.Errorf("resourceDiskUpdate: Disk ID %s - changing type of existing disk not allowed", d.Id())
}
*/
d.Partial(false)
// we may reuse dataSourceDiskRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return dataSourceDiskRead(d, m)
}
func resourceDiskDelete(d *schema.ResourceData, m interface{}) error {
// NOTE: this function tries to detach and destroy target Disk "permanently", so
// there is no way to restore it.
// If, however, the disk is attached to a compute, the method will
// fail (by failing the underpinning DECORt API call, which is issued with detach=false)
log.Debugf("resourceDiskDelete: called for Disk ID / name %d / %s, Account ID %d",
d.Get("disk_id").(int), d.Get("name").(string), d.Get("account_id").(int))
diskFacts, err := utilityDiskCheckPresence(d, m)
if diskFacts == "" {
// the specified Disk 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("diskId", d.Id())
// NOTE: we are not force-detaching disk from a compute (if attached) thus protecting
// data that may be on that disk from destruction.
// However, this may change in the future, as TF state management logic may want
// to delete disk resource BEFORE it is detached from compute instance, and, while
// perfectly OK from data preservation viewpoint, this is breaking expected TF workflow
// in the eyes of an experienced TF user
params.Add("detach", "0")
params.Add("permanently", "1")
controller := m.(*ControllerCfg)
_, err = controller.decortAPICall("POST", DisksDeleteAPI, params)
if err != nil {
return err
}
return nil
}
func resourceDiskExists(d *schema.ResourceData, m interface{}) (bool, error) {
// Reminder: according to Terraform rules, this function should not modify its ResourceData argument
log.Debugf("resourceDiskExists: called for Disk ID / name %d / %s, Account ID %d",
d.Get("disk_id").(int), d.Get("name").(string), d.Get("account_id").(int))
diskFacts, err := utilityDiskCheckPresence(d, m)
if diskFacts == "" {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceDiskSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Description: "Name of this disk. NOTE: disk names are NOT unique within an account. If disk ID is specified, disk name is ignored.",
},
"disk_id": {
Type: schema.TypeInt,
Optional: true,
Description: "ID of the disk to get. If disk ID is specified, then disk name and account ID are ignored.",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Description: "ID of the account this disk belongs to.",
},
"sep_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Storage end-point provider serving this disk. Cannot be changed for existing disk.",
},
"pool": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
Description: "Pool where this disk is located. Cannot be changed for existing disk.",
},
"size": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Size of the disk in GB. Note, that existing disks can only be grown in size.",
},
/* We moved "type" attribute to computed attributes section, as plugin manages disks of only
one type - "D", e.g. data disks.
"type": {
Type: schema.TypeString,
Optional: true,
Default: "D",
StateFunc: stateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"B", "D"}, false),
Description: "Optional type of this disk. Defaults to D, i.e. data disk. Cannot be changed for existing disks.",
},
*/
"description": {
Type: schema.TypeString,
Optional: true,
Default: "Disk resource managed by Terraform",
Description: "Optional user-defined text description of this disk.",
},
// The rest of the attributes are all computed
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account this disk belongs to.",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the image, which this disk was cloned from (if ever cloned).",
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of this disk.",
},
"sep_type": {
Type: schema.TypeString,
Computed: true,
Description: "Type of the storage end-point provider serving this disk.",
},
/*
"snapshots": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource {
Schema: snapshotSubresourceSchemaMake(),
},
Description: "List of user-created snapshots for this disk."
},
*/
}
return rets
}
func resourceDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Create: resourceDiskCreate,
Read: resourceDiskRead,
Update: resourceDiskUpdate,
Delete: resourceDiskDelete,
Exists: resourceDiskExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout180s,
Read: &Timeout30s,
Update: &Timeout180s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceDiskSchemaMake(),
}
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: 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.
@@ -18,37 +16,28 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"errors"
"net/url"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/flattens"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceImageCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("url", d.Get("url").(string))
@@ -98,43 +87,44 @@ func resourceImageCreate(ctx context.Context, d *schema.ResourceData, m interfac
}
api := ""
if isSync := d.Get("sync").(bool); !isSync {
isSync := d.Get("sync").(bool)
if !isSync {
api = imageCreateAPI
} else {
api = imageSyncCreateAPI
}
imageId, err := c.DecortAPICall(ctx, "POST", api, urlValues)
imageId, err := controller.decortAPICall("POST", api, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(imageId)
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceImageRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageRead: called for %s id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if image == nil {
d.SetId("")
return diag.FromErr(err)
return err
}
d.Set("name", image.Name)
@@ -169,7 +159,7 @@ func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{
d.Set("res_name", image.ResName)
d.Set("rescuecd", image.Rescuecd)
d.Set("architecture", image.Architecture)
d.Set("meta", flattens.FlattenMeta(image.Meta))
d.Set("meta", flattenMeta(image.Meta))
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
@@ -179,18 +169,18 @@ func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceImageDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if image == nil {
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if reason, ok := d.GetOk("reason"); ok {
@@ -202,22 +192,36 @@ func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interfac
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
_, err = c.DecortAPICall(ctx, "POST", imageDeleteAPI, urlValues)
_, err = controller.decortAPICall("POST", imageDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId("")
return nil
}
func resourceImageEditName(ctx context.Context, d *schema.ResourceData, m interface{}) error {
func resourceImageExists(d *schema.ResourceData, m interface{}) (bool, error) {
log.Debugf("resourceImageExists: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(d, m)
if image == nil {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceImageEditName(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageEditName: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
_, err := c.DecortAPICall(ctx, "POST", imageEditNameAPI, urlValues)
_, err := c.decortAPICall("POST", imageEditNameAPI, urlValues)
if err != nil {
return err
}
@@ -225,82 +229,40 @@ func resourceImageEditName(ctx context.Context, d *schema.ResourceData, m interf
return nil
}
func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceImageEdit(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
if d.HasChange("enabled") {
err := resourceImageChangeEnabled(ctx, d, m)
urlValues.Add("username", d.Get("username").(string))
urlValues.Add("password", d.Get("password").(string))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("bootable", strconv.FormatBool(d.Get("bootable").(bool)))
urlValues.Add("hotresize", strconv.FormatBool(d.Get("hot_resize").(bool)))
//_, err := c.decortAPICall("POST", imageEditAPI, urlValues)
_, err := c.decortAPICall("POST", imageEditAPI, urlValues)
if err != nil {
err = resourceImageRead(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
urlValues = &url.Values{}
return nil
}
if d.HasChange("name") {
err := resourceImageEditName(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("shared_with") {
err := resourceImageShare(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("computeci_id") {
err := resourceImageChangeComputeci(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("enabled_stacks") {
err := resourceImageUpdateNodes(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("link_to") {
err := resourceImageLink(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChanges("name", "username", "password", "account_id", "bootable", "hot_resize") {
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("username", d.Get("username").(string))
urlValues.Add("password", d.Get("password").(string))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("bootable", strconv.FormatBool(d.Get("bootable").(bool)))
urlValues.Add("hotresize", strconv.FormatBool(d.Get("hot_resize").(bool)))
_, err := c.DecortAPICall(ctx, "POST", imageEditAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceImageChangeEnabled(ctx context.Context, d *schema.ResourceData, m interface{}) error {
func resourceImageChangeEnabled(d *schema.ResourceDiff, m interface{}) error {
var api string
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if d.Get("enabled").(bool) {
@@ -308,7 +270,7 @@ func resourceImageChangeEnabled(ctx context.Context, d *schema.ResourceData, m i
} else {
api = imageDisableAPI
}
resp, err := c.DecortAPICall(ctx, "POST", api, urlValues)
resp, err := c.decortAPICall("POST", api, urlValues)
if err != nil {
return err
}
@@ -322,13 +284,13 @@ func resourceImageChangeEnabled(ctx context.Context, d *schema.ResourceData, m i
return nil
}
func resourceImageLink(ctx context.Context, d *schema.ResourceData, m interface{}) error {
func resourceImageLink(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceVirtualImageLink: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("targetId", strconv.Itoa(d.Get("link_to").(int)))
_, err := c.DecortAPICall(ctx, "POST", imageLinkAPI, urlValues)
_, err := c.decortAPICall("POST", imageLinkAPI, urlValues)
if err != nil {
return err
}
@@ -336,9 +298,9 @@ func resourceImageLink(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourceImageShare(ctx context.Context, d *schema.ResourceData, m interface{}) error {
func resourceImageShare(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageShare: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
accIds := d.Get("shared_with").([]interface{})
@@ -355,7 +317,7 @@ func resourceImageShare(ctx context.Context, d *schema.ResourceData, m interface
}
temp = "[" + temp + "]"
urlValues.Add("accounts", temp)
_, err := c.DecortAPICall(ctx, "POST", imageShareAPI, urlValues)
_, err := c.decortAPICall("POST", imageShareAPI, urlValues)
if err != nil {
return err
}
@@ -363,8 +325,8 @@ func resourceImageShare(ctx context.Context, d *schema.ResourceData, m interface
return nil
}
func resourceImageChangeComputeci(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
func resourceImageChangeComputeci(d *schema.ResourceDiff, m interface{}) error {
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
@@ -379,7 +341,7 @@ func resourceImageChangeComputeci(ctx context.Context, d *schema.ResourceData, m
api = imageComputeciSetAPI
}
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
_, err := c.decortAPICall("POST", api, urlValues)
if err != nil {
return err
}
@@ -387,9 +349,9 @@ func resourceImageChangeComputeci(ctx context.Context, d *schema.ResourceData, m
return nil
}
func resourceImageUpdateNodes(ctx context.Context, d *schema.ResourceData, m interface{}) error {
func resourceImageUpdateNodes(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageUpdateNodes: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
enabledStacks := d.Get("enabled_stacks").([]interface{})
@@ -404,7 +366,7 @@ func resourceImageUpdateNodes(ctx context.Context, d *schema.ResourceData, m int
}
temp = "[" + temp + "]"
urlValues.Add("enabledStacks", temp)
_, err := c.DecortAPICall(ctx, "POST", imageUpdateNodesAPI, urlValues)
_, err := c.decortAPICall("POST", imageUpdateNodesAPI, urlValues)
if err != nil {
return err
}
@@ -655,26 +617,88 @@ func resourceImageSchemaMake() map[string]*schema.Schema {
}
}
func ResourceImage() *schema.Resource {
func resourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
DeleteContext: resourceImageDelete,
Create: resourceImageCreate,
Read: resourceImageRead,
Update: resourceImageEdit,
Delete: resourceImageDelete,
Exists: resourceImageExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout60s,
Read: &constants.Timeout30s,
Update: &constants.Timeout60s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName),
customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageUpdateNodes),
),
Schema: resourceImageSchemaMake(),
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,21 +16,15 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package k8s
package decort
import (
"context"
"encoding/json"
"fmt"
"net/url"
@@ -40,17 +32,14 @@ import (
"strings"
"time"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sCreate: called with name %s, rg %d", d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
@@ -84,39 +73,38 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
//}
urlValues.Add("withLB", strconv.FormatBool(true))
if extNet, ok := d.GetOk("extnet_id"); ok {
urlValues.Add("extnetId", strconv.Itoa(extNet.(int)))
} else {
urlValues.Add("extnetId", "0")
}
//if extNet, ok := d.GetOk("extnet_id"); ok {
//urlValues.Add("extnetId", strconv.Itoa(extNet.(int)))
//}
urlValues.Add("extnetId", strconv.Itoa(0))
//if desc, ok := d.GetOk("desc"); ok {
//urlValues.Add("desc", desc.(string))
//}
resp, err := c.DecortAPICall(ctx, "POST", K8sCreateAPI, urlValues)
resp, err := controller.decortAPICall("POST", K8sCreateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
urlValues = &url.Values{}
urlValues.Add("auditId", strings.Trim(resp, `"`))
for {
resp, err := c.DecortAPICall(ctx, "POST", AsyncTaskGetAPI, urlValues)
resp, err := controller.decortAPICall("POST", AsyncTaskGetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
task := AsyncTask{}
if err := json.Unmarshal([]byte(resp), &task); err != nil {
return diag.FromErr(err)
return err
}
log.Debugf("resourceK8sCreate: instance creating - %s", task.Stage)
if task.Completed {
if task.Error != "" {
return diag.FromErr(fmt.Errorf("cannot create k8s instance: %v", task.Error))
return fmt.Errorf("cannot create k8s instance: %v", task.Error)
}
d.SetId(strconv.Itoa(int(task.Result)))
@@ -126,31 +114,16 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
time.Sleep(time.Second * 10)
}
k8s, err := utilityK8sCheckPresence(ctx, d, m)
k8s, err := utilityK8sCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.Set("default_wg_id", k8s.Groups.Workers[0].ID)
urlValues = &url.Values{}
urlValues.Add("lbId", strconv.Itoa(k8s.LbID))
resp, err = c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
var lb LbRecord
if err := json.Unmarshal([]byte(resp), &lb); err != nil {
return diag.FromErr(err)
}
d.Set("extnet_id", lb.ExtNetID)
d.Set("lb_ip", lb.PrimaryNode.FrontendIP)
urlValues = &url.Values{}
urlValues.Add("k8sId", d.Id())
kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues)
kubeconfig, err := controller.decortAPICall("POST", K8sGetConfigAPI, urlValues)
if err != nil {
log.Warnf("could not get kubeconfig: %v", err)
}
@@ -159,13 +132,13 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sRead: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityK8sCheckPresence(ctx, d, m)
k8s, err := utilityK8sCheckPresence(d, m)
if k8s == nil {
d.SetId("")
return diag.FromErr(err)
return err
}
d.Set("name", k8s.Name)
@@ -176,25 +149,10 @@ func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{})
d.Set("workers", nodeToResource(k8s.Groups.Workers[0]))
d.Set("default_wg_id", k8s.Groups.Workers[0].ID)
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("lbId", strconv.Itoa(k8s.LbID))
resp, err := c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
var lb LbRecord
if err := json.Unmarshal([]byte(resp), &lb); err != nil {
return diag.FromErr(err)
}
d.Set("extnet_id", lb.ExtNetID)
d.Set("lb_ip", lb.PrimaryNode.FrontendIP)
urlValues = &url.Values{}
urlValues.Add("k8sId", d.Id())
kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues)
kubeconfig, err := controller.decortAPICall("POST", K8sGetConfigAPI, urlValues)
if err != nil {
log.Warnf("could not get kubeconfig: %v", err)
}
@@ -203,26 +161,26 @@ func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{})
return nil
}
func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sUpdate: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
if d.HasChange("name") {
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("name", d.Get("name").(string))
_, err := c.DecortAPICall(ctx, "POST", K8sUpdateAPI, urlValues)
_, err := controller.decortAPICall("POST", K8sUpdateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
}
if d.HasChange("workers") {
k8s, err := utilityK8sCheckPresence(ctx, d, m)
k8s, err := utilityK8sCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
wg := k8s.Groups.Workers[0]
@@ -234,14 +192,16 @@ func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{
if newWorkers.Num > wg.Num {
urlValues.Add("num", strconv.Itoa(newWorkers.Num-wg.Num))
if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues); err != nil {
return diag.FromErr(err)
_, err := controller.decortAPICall("POST", K8sWorkerAddAPI, urlValues)
if err != nil {
return err
}
} else {
for i := wg.Num - 1; i >= newWorkers.Num; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues); err != nil {
return diag.FromErr(err)
_, err := controller.decortAPICall("POST", K8sWorkerDeleteAPI, urlValues)
if err != nil {
return err
}
}
}
@@ -250,30 +210,41 @@ func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourceK8sDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sDelete: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityK8sCheckPresence(ctx, d, m)
k8s, err := utilityK8sCheckPresence(d, m)
if k8s == nil {
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("permanently", "true")
_, err = c.DecortAPICall(ctx, "POST", K8sDeleteAPI, urlValues)
_, err = controller.decortAPICall("POST", K8sDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
func resourceK8sExists(d *schema.ResourceData, m interface{}) (bool, error) {
log.Debugf("resourceK8sExists: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityK8sCheckPresence(d, m)
if k8s == nil {
return false, err
}
return true, nil
}
func resourceK8sSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"name": {
@@ -332,13 +303,13 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
//Description: "Create k8s with load balancer if true.",
//},
"extnet_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
Description: "ID of the external network to connect workers to. If omitted network will be chosen by the platfom.",
},
//"extnet_id": {
//Type: schema.TypeInt,
//Optional: true,
//ForceNew: true,
//Default: 0,
//Description: "ID of the external network to connect workers to.",
//},
//"desc": {
//Type: schema.TypeString,
@@ -346,12 +317,6 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
//Description: "Text description of this instance.",
//},
"lb_ip": {
Type: schema.TypeString,
Computed: true,
Description: "IP address of default load balancer.",
},
"default_wg_id": {
Type: schema.TypeInt,
Computed: true,
@@ -366,25 +331,26 @@ func resourceK8sSchemaMake() map[string]*schema.Schema {
}
}
func ResourceK8s() *schema.Resource {
func resourceK8s() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceK8sCreate,
ReadContext: resourceK8sRead,
UpdateContext: resourceK8sUpdate,
DeleteContext: resourceK8sDelete,
Create: resourceK8sCreate,
Read: resourceK8sRead,
Update: resourceK8sUpdate,
Delete: resourceK8sDelete,
Exists: resourceK8sExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout20m,
Read: &constants.Timeout30s,
Update: &constants.Timeout20m,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout10m,
Read: &Timeout30s,
Update: &Timeout10m,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceK8sSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,35 +16,26 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package k8s
package decort
import (
"context"
"net/url"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceK8sWgCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sWgCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgCreate: called with k8s id %d", d.Get("k8s_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("name", d.Get("name").(string))
@@ -55,9 +44,9 @@ func resourceK8sWgCreate(ctx context.Context, d *schema.ResourceData, m interfac
urlValues.Add("workerRam", strconv.Itoa(d.Get("ram").(int)))
urlValues.Add("workerDisk", strconv.Itoa(d.Get("disk").(int)))
resp, err := c.DecortAPICall(ctx, "POST", K8sWgCreateAPI, urlValues)
resp, err := controller.decortAPICall("POST", K8sWgCreateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(resp)
@@ -94,13 +83,13 @@ func resourceK8sWgCreate(ctx context.Context, d *schema.ResourceData, m interfac
return nil
}
func resourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sWgRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgRead: called with k8s id %d", d.Get("k8s_id").(int))
wg, err := utilityK8sWgCheckPresence(ctx, d, m)
wg, err := utilityK8sWgCheckPresence(d, m)
if wg == nil {
d.SetId("")
return diag.FromErr(err)
return err
}
d.Set("name", wg.Name)
@@ -112,32 +101,34 @@ func resourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourceK8sWgUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sWgUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgUpdate: called with k8s id %d", d.Get("k8s_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
wg, err := utilityK8sWgCheckPresence(ctx, d, m)
wg, err := utilityK8sWgCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return nil
}
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("workersGroupId", d.Id())
if newNum := d.Get("num").(int); newNum > wg.Num {
newNum := d.Get("num").(int)
if newNum > wg.Num {
urlValues.Add("num", strconv.Itoa(newNum-wg.Num))
_, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues)
_, err := controller.decortAPICall("POST", K8sWorkerAddAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
} else {
for i := wg.Num - 1; i >= newNum; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
_, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues)
_, err := controller.decortAPICall("POST", K8sWorkerDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
}
}
@@ -145,30 +136,44 @@ func resourceK8sWgUpdate(ctx context.Context, d *schema.ResourceData, m interfac
return nil
}
func resourceK8sWgDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceK8sWgDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceK8sWgDelete: called with k8s id %d", d.Get("k8s_id").(int))
wg, err := utilityK8sWgCheckPresence(ctx, d, m)
wg, err := utilityK8sWgCheckPresence(d, m)
if wg == nil {
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("workersGroupId", strconv.Itoa(wg.ID))
_, err = c.DecortAPICall(ctx, "POST", K8sWgDeleteAPI, urlValues)
_, err = controller.decortAPICall("POST", K8sWgDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
func resourceK8sWgExists(d *schema.ResourceData, m interface{}) (bool, error) {
log.Debugf("resourceK8sWgExists: called with k8s id %d", d.Get("k8s_id").(int))
wg, err := utilityK8sWgCheckPresence(d, m)
if wg == nil {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceK8sWgSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"k8s_id": {
@@ -218,25 +223,26 @@ func resourceK8sWgSchemaMake() map[string]*schema.Schema {
}
}
func ResourceK8sWg() *schema.Resource {
func resourceK8sWg() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceK8sWgCreate,
ReadContext: resourceK8sWgRead,
UpdateContext: resourceK8sWgUpdate,
DeleteContext: resourceK8sWgDelete,
Create: resourceK8sWgCreate,
Read: resourceK8sWgRead,
Update: resourceK8sWgUpdate,
Delete: resourceK8sWgDelete,
Exists: resourceK8sWgExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout20m,
Read: &constants.Timeout30s,
Update: &constants.Timeout20m,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout10m,
Read: &Timeout30s,
Update: &Timeout10m,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceK8sWgSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,37 +16,28 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package pfw
package decort
import (
"context"
"fmt"
"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/v2/helper/validation"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
log "github.com/sirupsen/logrus"
)
func resourcePfwCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourcePfwCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourcePfwCreate: called for compute %d", d.Get("compute_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("publicPortStart", strconv.Itoa(d.Get("public_port_start").(int)))
@@ -59,16 +48,16 @@ func resourcePfwCreate(ctx context.Context, d *schema.ResourceData, m interface{
urlValues.Add("publicPortEnd", strconv.Itoa(portEnd.(int)))
}
pfwId, err := c.DecortAPICall(ctx, "POST", ComputePfwAddAPI, urlValues)
pfwId, err := controller.decortAPICall("POST", ComputePfwAddAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(fmt.Sprintf("%d-%s", d.Get("compute_id").(int), pfwId))
pfw, err := utilityPfwCheckPresence(ctx, d, m)
pfw, err := utilityPfwCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.Set("local_ip", pfw.LocalIP)
@@ -79,13 +68,13 @@ func resourcePfwCreate(ctx context.Context, d *schema.ResourceData, m interface{
return nil
}
func resourcePfwRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourcePfwRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourcePfwRead: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id())
pfw, err := utilityPfwCheckPresence(ctx, d, m)
pfw, err := utilityPfwCheckPresence(d, m)
if pfw == nil {
d.SetId("")
return diag.FromErr(err)
return err
}
d.Set("compute_id", pfw.ComputeID)
@@ -98,30 +87,44 @@ func resourcePfwRead(ctx context.Context, d *schema.ResourceData, m interface{})
return nil
}
func resourcePfwDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourcePfwDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourcePfwDelete: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id())
pfw, err := utilityPfwCheckPresence(ctx, d, m)
pfw, err := utilityPfwCheckPresence(d, m)
if pfw == nil {
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("ruleId", strconv.Itoa(pfw.ID))
_, err = c.DecortAPICall(ctx, "POST", ComputePfwDelAPI, urlValues)
_, err = controller.decortAPICall("POST", ComputePfwDelAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
func resourcePfwExists(d *schema.ResourceData, m interface{}) (bool, error) {
log.Debugf("resourcePfwExists: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id())
pfw, err := utilityPfwCheckPresence(d, m)
if pfw == nil {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourcePfwSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
@@ -142,7 +145,6 @@ func resourcePfwSchemaMake() map[string]*schema.Schema {
"public_port_end": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validation.IntBetween(1, 65535),
Description: "End port number (inclusive) for the ranged rule.",
@@ -172,24 +174,25 @@ func resourcePfwSchemaMake() map[string]*schema.Schema {
}
}
func ResourcePfw() *schema.Resource {
func resourcePfw() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourcePfwCreate,
ReadContext: resourcePfwRead,
DeleteContext: resourcePfwDelete,
Create: resourcePfwCreate,
Read: resourcePfwRead,
Delete: resourcePfwDelete,
Exists: resourcePfwExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout60s,
Read: &constants.Timeout30s,
Update: &constants.Timeout60s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourcePfwSchemaMake(),

View File

@@ -1,8 +1,5 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -10,7 +7,7 @@ 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
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
@@ -18,44 +15,37 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package rg
package decort
import (
"context"
"encoding/json"
"fmt"
"net/url"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/location"
log "github.com/sirupsen/logrus"
"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/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceResgroupCreate(d *schema.ResourceData, m interface{}) error {
// First validate that we have all parameters required to create the new Resource Group
// Valid account ID is required to create new resource group
// obtain Account ID by account name - it should not be zero on success
validated_account_id, err := utilityGetAccountIdBySchema(d, m)
if err != nil {
return err
}
rg_name, arg_set := d.GetOk("name")
if !arg_set {
return diag.FromErr(fmt.Errorf("Cannot create new RG: missing name."))
return fmt.Errorf("Cannot create new RG: missing name.")
}
/* Current version of provider works with default grid id (same is true for disk resources)
@@ -71,7 +61,7 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
// all required parameters are set in the schema - we can continue with RG creation
log.Debugf("resourceResgroupCreate: called for RG name %s, account ID %d",
rg_name.(string), d.Get("account_id").(int))
rg_name.(string), validated_account_id)
// quota settings are optional
set_quota := false
@@ -79,20 +69,20 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
arg_value, arg_set := d.GetOk("quota")
if arg_set {
log.Debugf("resourceResgroupCreate: setting Quota on RG requested")
quota_record = makeQuotaRecord(arg_value.([]interface{}))
quota_record, _ = makeQuotaRecord(arg_value.([]interface{}))
set_quota = true
}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d",
c.GetDecortUsername(),
rg_name.(string), d.Get("account_id").(int))
controller.getDecortUsername(),
rg_name.(string), validated_account_id)
url_values := &url.Values{}
url_values.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
url_values.Add("accountId", fmt.Sprintf("%d", validated_account_id))
url_values.Add("name", rg_name.(string))
url_values.Add("gid", fmt.Sprintf("%d", location.DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
url_values.Add("owner", c.GetDecortUsername())
url_values.Add("gid", fmt.Sprintf("%d", DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
url_values.Add("owner", controller.getDecortUsername())
// pass quota values as set
if set_quota {
@@ -125,47 +115,34 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
url_values.Add("extIp", ext_ip.(string))
}
api_resp, err := c.DecortAPICall(ctx, "POST", ResgroupCreateAPI, url_values)
api_resp, err := controller.decortAPICall("POST", ResgroupCreateAPI, url_values)
if err != nil {
return diag.FromErr(err)
return err
}
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)
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))
}
// re-read newly created RG to make sure schema contains complete and up to date set of specifications
return resourceResgroupRead(ctx, d, m)
return resourceResgroupRead(d, m)
}
func resourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceResgroupRead: called for RG name %s, account ID %d",
func resourceResgroupRead(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceResgroupRead: called for RG name %s, account ID %s",
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
rg_facts, err := utilityResgroupCheckPresence(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
d.SetId("") // ensure ID is empty
return diag.FromErr(err)
return err
}
return diag.FromErr(flattenResgroup(d, rg_facts))
return flattenResgroup(d, rg_facts)
}
func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceResgroupUpdate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceResgroupUpdate: called for RG name %s, account ID %d",
d.Get("name").(string), d.Get("account_id").(int))
@@ -180,18 +157,19 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
for _, attr := range []string{"def_net_type", "ipcidr", "ext_ip"} {
attr_new, attr_old := d.GetChange("def_net_type")
if attr_new.(string) != attr_old.(string) {
return diag.FromErr(fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing %s for existing RG is not allowed", d.Id(), attr))
return fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing %s for existing RG is not allowed", d.Id(), attr)
}
}
attr_new, attr_old := d.GetChange("ext_net_id")
if attr_new.(int) != attr_old.(int) {
return diag.FromErr(fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing ext_net_id for existing RG is not allowed", d.Id()))
return fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing ext_net_id for existing RG is not allowed", d.Id())
}
do_general_update := false // will be true if general RG update is necessary (API rg/update)
do_general_update := false // will be true if general RG update is necessary (API rg/update)
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
url_values := &url.Values{}
url_values.Add("rgId", d.Id())
@@ -208,9 +186,9 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
quota_value, quota_set := d.GetOk("quota")
if quota_set {
log.Debugf("resourceResgroupUpdate: quota specified - looking for deltas from the old quota.")
quotarecord_new := makeQuotaRecord(quota_value.([]interface{}))
quotarecord_new, _ := makeQuotaRecord(quota_value.([]interface{}))
quota_value_old, _ := d.GetChange("quota") // returns old as 1st, new as 2nd return value
quotarecord_old := makeQuotaRecord(quota_value_old.([]interface{}))
quotarecord_old, _ := makeQuotaRecord(quota_value_old.([]interface{}))
if quotarecord_new.Cpu != quotarecord_old.Cpu {
do_general_update = true
@@ -255,28 +233,25 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
if do_general_update {
log.Debugf("resourceResgroupUpdate: detected delta between new and old RG specs - updating the RG")
_, err := c.DecortAPICall(ctx, "POST", ResgroupUpdateAPI, url_values)
_, err := controller.decortAPICall("POST", ResgroupUpdateAPI, url_values)
if err != nil {
return diag.FromErr(err)
return err
}
} else {
log.Debugf("resourceResgroupUpdate: no difference between old and new state - no update on the RG will be done")
}
return resourceResgroupRead(ctx, d, m)
return resourceResgroupRead(d, m)
}
func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceResgroupDelete(d *schema.ResourceData, m interface{}) error {
// NOTE: this method forcibly destroys target resource group with flag "permanently", so there is no way to
// restore the destroyed resource group as well all Computes & VINSes that existed in it
log.Debugf("resourceResgroupDelete: called for RG name %s, account ID %d",
log.Debugf("resourceResgroupDelete: called for RG name %s, account ID %s",
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
rg_facts, err := utilityResgroupCheckPresence(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
@@ -288,34 +263,47 @@ func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m inter
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)
controller := m.(*ControllerCfg)
_, err = controller.decortAPICall("POST", ResgroupDeleteAPI, url_values)
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
func ResourceResgroup() *schema.Resource {
func resourceResgroupExists(d *schema.ResourceData, m interface{}) (bool, error) {
// Reminder: according to Terraform rules, this function should NOT modify ResourceData argument
rg_facts, err := utilityResgroupCheckPresence(d, m)
if rg_facts == "" {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceResgroup() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceResgroupCreate,
ReadContext: resourceResgroupRead,
UpdateContext: resourceResgroupUpdate,
DeleteContext: resourceResgroupDelete,
Create: resourceResgroupCreate,
Read: resourceResgroupRead,
Update: resourceResgroupUpdate,
Delete: resourceResgroupDelete,
Exists: resourceResgroupExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout180s,
Read: &constants.Timeout30s,
Update: &constants.Timeout180s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout180s,
Read: &Timeout30s,
Update: &Timeout180s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: map[string]*schema.Schema{
@@ -326,18 +314,18 @@ func ResourceResgroup() *schema.Resource {
},
"account_id": {
Type: schema.TypeInt,
Required: true,
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "Unique ID of the account, which this resource group belongs to.",
Description: "Unique ID of the account, which this resource group belongs to.",
},
"def_net_type": {
Type: schema.TypeString,
Optional: true,
Default: "PRIVATE",
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.",
Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.",
},
"def_net_id": {
@@ -366,7 +354,7 @@ func ResourceResgroup() *schema.Resource {
},
/* commented out, as in this version of provider we use default Grid ID
"grid_id": {
"grid_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0, // if 0 is passed, default Grid ID will be used
@@ -379,7 +367,6 @@ func ResourceResgroup() *schema.Resource {
"quota": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(),
@@ -400,30 +387,30 @@ func ResourceResgroup() *schema.Resource {
},
/*
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of 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,
MaxItems: LimitMaxVinsPerResgroup,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of VINs deployed in 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.",
"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.",
},
*/
},
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,38 +16,31 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package vins
package decort
import (
"context"
// "encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"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/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
// "github.com/hashicorp/terraform-plugin-sdk/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 -
// 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
@@ -58,13 +49,13 @@ func ipcidrDiffSupperss(key, oldVal, newVal string, d *schema.ResourceData) bool
return true // suppress difference
}
func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceVinsCreate(d *schema.ResourceData, m interface{}) error {
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))
d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
apiToCall := VinsCreateInAccountAPI
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
@@ -74,11 +65,11 @@ func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface
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
// 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())
return fmt.Errorf("resourceVinsCreate: ViNS name %s - no valid account and/or resource group ID specified", d.Id())
}
urlValues.Add("accountId", fmt.Sprintf("%d", argVal.(int)))
}
@@ -88,14 +79,14 @@ func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface
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!
/*
Commented out, as we've made "ext_net_ip" parameter non-configurable via Terraform!
// 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))
}
// 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))
}
*/
} else {
// ext_net_id is set to a negative value - connect to default external network
@@ -109,15 +100,15 @@ func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface
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)
apiResp, err := controller.decortAPICall("POST", apiToCall, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(apiResp) // update ID of the resource to tell Terraform that the ViNS resource exists
@@ -125,32 +116,34 @@ func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface
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
// 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
// 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)
return dataSourceVinsRead(d, m)
}
func resourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
func resourceVinsRead(d *schema.ResourceData, m interface{}) error {
vinsFacts, err := utilityVinsCheckPresence(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
return diag.FromErr(err)
return err
}
return flattenVins(d, vinsFacts)
}
func resourceVinsUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceVinsUpdate(d *schema.ResourceData, m interface{}) error {
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))
d.Id(), d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
d.Partial(true)
// 1. Handle external network connection change
oldExtNetId, newExtNedId := d.GetChange("ext_net_id")
if oldExtNetId.(int) != newExtNedId.(int) {
@@ -161,36 +154,37 @@ func resourceVinsUpdate(ctx context.Context, d *schema.ResourceData, m interface
if oldExtNetId.(int) > 0 {
// there was preexisting external net connection - disconnect ViNS
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetDisconnectAPI, extnetParams)
_, err := controller.decortAPICall("POST", VinsExtNetDisconnectAPI, extnetParams)
if err != nil {
return diag.FromErr(err)
return err
}
}
if newExtNedId.(int) > 0 {
// new external network connection requested - connect ViNS
extnetParams.Add("netId", fmt.Sprintf("%d", newExtNedId.(int)))
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetConnectAPI, extnetParams)
_, err := controller.decortAPICall("POST", VinsExtNetConnectAPI, extnetParams)
if err != nil {
return diag.FromErr(err)
return err
}
}
d.SetPartial("ext_net_id")
}
// we may reuse dataSourceVinsRead here as we maintain similarity
d.Partial(false)
// we may reuse dataSourceVinsRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return dataSourceVinsRead(ctx, d, m)
return dataSourceVinsRead(d, m)
}
func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceVinsDelete(d *schema.ResourceData, m interface{}) error {
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)
vinsFacts, err := utilityVinsCheckPresence(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
@@ -198,25 +192,40 @@ func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface
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
params.Add("force", "1") // disconnect all computes before deleting ViNS
params.Add("permanently", "1") // delete ViNS immediately bypassing recycle bin
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", VinsDeleteAPI, params)
controller := m.(*ControllerCfg)
_, err = controller.decortAPICall("POST", VinsDeleteAPI, params)
if err != nil {
return diag.FromErr(err)
return err
}
return nil
}
func resourceVinsExists(d *schema.ResourceData, m interface{}) (bool, error) {
// Reminder: according to Terraform rules, this function should not modify its ResourceData argument
log.Debugf("resourceVinsExists: 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))
vinsFacts, err := utilityVinsCheckPresence(d, m)
if vinsFacts == "" {
if err != nil {
return false, err
}
return false, nil
}
return true, nil
}
func resourceVinsSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
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.",
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.
@@ -237,25 +246,25 @@ func resourceVinsSchemaMake() map[string]*schema.Schema {
},
"account_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
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.",
Description: "ID of the account, which this ViNS belongs to. For ViNS created at account level, resource group ID is 0.",
},
"ext_net_id": {
Type: schema.TypeInt,
Required: true,
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.",
Description: "ID of the external network this ViNS is connected to. Pass 0 if no external connection required.",
},
"ipcidr": {
Type: schema.TypeString,
Optional: true,
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: ipcidrDiffSupperss,
Description: "Network address to use by this ViNS. This parameter is only valid when creating new ViNS.",
Description: "Network address to use by this ViNS. This parameter is only valid when creating new ViNS.",
},
"description": {
@@ -282,25 +291,26 @@ func resourceVinsSchemaMake() map[string]*schema.Schema {
return rets
}
func ResourceVins() *schema.Resource {
func resourceVins() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceVinsCreate,
ReadContext: resourceVinsRead,
UpdateContext: resourceVinsUpdate,
DeleteContext: resourceVinsDelete,
Create: resourceVinsCreate,
Read: resourceVinsRead,
Update: resourceVinsUpdate,
Delete: resourceVinsDelete,
Exists: resourceVinsExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout180s,
Read: &constants.Timeout30s,
Update: &constants.Timeout180s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout180s,
Read: &Timeout30s,
Update: &Timeout180s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceVinsSchemaMake(),

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: 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.
@@ -18,59 +16,51 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"net/url"
"strconv"
"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"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceVirtualImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceVirtualImageCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("targetId", strconv.Itoa(d.Get("target_id").(int)))
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateVirtualAPI, urlValues)
imageId, err := controller.decortAPICall("POST", imageCreateVirtualAPI, urlValues)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(imageId)
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return diag.FromErr(err)
return err
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
@@ -318,27 +308,95 @@ func resourceVirtualImageSchemaMake() map[string]*schema.Schema {
}
}
func ResourceVirtualImage() *schema.Resource {
func resourceVirtualImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
CreateContext: resourceVirtualImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
DeleteContext: resourceImageDelete,
Create: resourceVirtualImageCreate,
Read: resourceImageRead,
Update: resourceImageEdit,
Delete: resourceImageDelete,
Exists: resourceImageExists,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout60s,
Read: &constants.Timeout30s,
Update: &constants.Timeout60s,
Delete: &constants.Timeout60s,
Default: &constants.Timeout60s,
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("link_to", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageLink),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName),
customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageUpdateNodes),
),
Schema: resourceVirtualImageSchemaMake(),
}
}

104
decort/ssh_subresource.go Normal file
View File

@@ -0,0 +1,104 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
package decort
import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
/*
func makeSshKeysConfig(arg_list []interface{}) (sshkeys []SshKeyConfig, count int) {
count = len(arg_list)
if count < 1 {
return nil, 0
}
sshkeys = make([]SshKeyConfig, count)
var subres_data map[string]interface{}
for index, value := range arg_list {
subres_data = value.(map[string]interface{})
sshkeys[index].User = subres_data["user"].(string)
sshkeys[index].SshKey = subres_data["public_key"].(string)
sshkeys[index].UserShell = subres_data["shell"].(string)
}
return sshkeys, count
}
*/
func makeSshKeysArgString(arg_list []interface{}) string {
// This function expects arg_list = data.Get("ssh_keys"), where "data" is a populated schema for Compute
// Resource (see func resourceCompute() definition) or Compute Data Source (see func dataSourceCompute())
// Prepare a string with username and public ssh key value in a format recognized by cloud-init utility.
// It is designed to be passed as "userdata" argument of virtual machine create API call.
// The following format is expected:
// '{"users": [{"ssh-authorized-keys": ["SSH_PUBCIC_KEY_VALUE"], "shell": "SHELL_VALUE", "name": "USERNAME_VALUE"}, {...}, ]}'
/*
`%s\n
- name: %s\n
ssh-authorized-keys:
- %s\n
shell: /bin/bash`
*/
if len(arg_list) < 1 {
return ""
}
out := `{"users": [`
const UserdataTemplate = `%s{"ssh-authorized-keys": ["%s"], "shell": "%s", "name": "%s"}, `
const out_suffix = `]}`
for _, value := range arg_list {
subres_data := value.(map[string]interface{})
out = fmt.Sprintf(UserdataTemplate, out, subres_data["public_key"].(string), subres_data["shell"].(string), subres_data["user"].(string))
}
out = fmt.Sprintf("%s %s", out, out_suffix)
return out
}
func sshSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"user": {
Type: schema.TypeString,
Required: true,
Description: "Name of the guest OS user of a new compute, for which the following SSH key will be authorized.",
},
"public_key": {
Type: schema.TypeString,
Required: true,
Description: "Public SSH key to authorize to the specified guest OS user on the compute being created.",
},
"shell": {
Type: schema.TypeString,
Optional: true,
Default: "/bin/bash",
Description: "Guest user shell. This parameter is optional, default is /bin/bash.",
},
}
return rets
}

156
decort/utility_account.go Normal file
View File

@@ -0,0 +1,156 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
"net/url"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func utilityAccountCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
accId, argSet := d.GetOk("account_id")
if argSet {
// get Account right away by its ID
log.Debugf("utilityAccountCheckPresence: locating Account by its ID %d", accId.(int))
urlValues.Add("accountId", fmt.Sprintf("%d", accId.(int)))
apiResp, err := controller.decortAPICall("POST", AccountsGetAPI, urlValues)
if err != nil {
return "", err
}
return apiResp, nil
}
accName, argSet := d.GetOk("name")
if !argSet {
// neither ID nor name - no account for you!
return "", fmt.Errorf("Cannot check account presence if name is empty and no account ID specified")
}
apiResp, err := controller.decortAPICall("POST", AccountsListAPI, urlValues)
if err != nil {
return "", err
}
// log.Debugf("%s", apiResp)
// log.Debugf("utilityAccountCheckPresence: ready to decode response body from %q", AccountsListAPI)
accList := AccountsListResp{}
err = json.Unmarshal([]byte(apiResp), &accList)
if err != nil {
return "", err
}
log.Debugf("utilityAccountCheckPresence: traversing decoded Json of length %d", len(accList))
for index, item := range accList {
// match by account name
if item.Name == accName.(string) {
log.Debugf("utilityAccountCheckPresence: match account name %q / ID %d at index %d",
item.Name, item.ID, index)
// NB: unlike accounts/get API, accounts/list API returns abridged set of account info,
// for instance it does not return quotas
reencodedItem, err := json.Marshal(item)
if err != nil {
return "", err
}
return string(reencodedItem[:]), nil
}
}
return "", fmt.Errorf("Cannot find account name %q", accName.(string))
}
func utilityGetAccountIdBySchema(d *schema.ResourceData, m interface{}) (int, error) {
/*
This function expects schema that contains the following two elements:
"account_name": &schema.Schema{
Type: schema.TypeString,
Required: Optional,
Description: "Name of the account, ....",
},
"account_id": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Description: "Unique ID of the account, ....",
},
Then it will check, which argument is set, and if account name is present, it will
initiate API calls to the DECORT cloud controller and try to match relevant account
by the name.
NOTE that for some resources (most notably, Resource Group) "account_name" attribute is
marked as "Computed: true", so the only way to fully identify Resource Group is to specify
"account_id", which is marked as "Required: true"
*/
accId, argSet := d.GetOk("account_id")
if argSet {
if accId.(int) > 0 {
return accId.(int), nil
}
return 0, fmt.Errorf("Account ID must be positive")
}
accName, argSet := d.GetOk("account_name")
if !argSet {
return 0, fmt.Errorf("Either non-empty account name or valid account ID must be specified")
}
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
apiResp, err := controller.decortAPICall("POST", AccountsListAPI, urlValues)
if err != nil {
return 0, err
}
model := AccountsListResp{}
err = json.Unmarshal([]byte(apiResp), &model)
if err != nil {
return 0, err
}
log.Debugf("utilityGetAccountIdBySchema: traversing decoded Json of length %d", len(model))
for index, item := range model {
// need to match Account by name
if item.Name == accName.(string) {
log.Debugf("utilityGetAccountIdBySchema: match Account name %q / ID %d at index %d",
item.Name, item.ID, index)
return item.ID, nil
}
}
return 0, fmt.Errorf("Cannot find account %q for the current user. Check account name and your access rights", accName.(string))
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,44 +16,36 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package kvmvm
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceData, m interface{}, do_delta bool) error {
func (ctrl *ControllerCfg) utilityComputeExtraDisksConfigure(d *schema.ResourceData, do_delta bool) error {
// d is filled with data according to computeResource schema, so extra disks config is retrieved via "extra_disks" key
// If do_delta is true, this function will identify changes between new and existing specs for extra disks and try to
// If do_delta is true, this function will identify changes between new and existing specs for extra disks and try to
// update compute configuration accordingly
// Otherwise it will apply whatever is found in the new set of "extra_disks" right away.
// Otherwise it will apply whatever is found in the new set of "extra_disks" right away.
// Primary use of do_delta=false is when calling this function from compute Create handler.
// Note that this function will not abort on API errors, but will continue to configure (attach / detach) other individual
// Note that this function will not abort on API errors, but will continue to configure (attach / detach) other individual
// disks via atomic API calls. However, it will not retry failed manipulation on the same disk.
c := m.(*controller.ControllerCfg)
log.Debugf("utilityComputeExtraDisksConfigure: called for Compute ID %s with do_delta = %t", d.Id(), do_delta)
log.Debugf("utilityComputeExtraDisksConfigure: called for Compute ID %s with do_delta = %b", d.Id(), do_delta)
// NB: as of rc-1.25 "extra_disks" are TypeSet with the elem of TypeInt
old_set, new_set := d.GetChange("extra_disks")
@@ -72,7 +62,7 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", disk.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskAttachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeDiskAttachAPI, urlValues)
if err != nil {
// failed to attach extra disk - partial resource update
apiErrCount++
@@ -81,11 +71,11 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
}
if apiErrCount > 0 {
log.Errorf("utilityComputeExtraDisksConfigure: there were %d error(s) when attaching disks to Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
log.Errorf("utilityComputeExtraDisksConfigure: there were %d error(s) when attaching disks to Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
return lastSavedError
}
return nil
}
@@ -95,7 +85,7 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", diskId.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskDetachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeDiskDetachAPI, urlValues)
if err != nil {
// failed to detach disk - there will be partial resource update
log.Errorf("utilityComputeExtraDisksConfigure: failed to detach disk ID %d from Compute ID %s: %s", diskId.(int), d.Id(), err)
@@ -110,7 +100,7 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", diskId.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskAttachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeDiskAttachAPI, urlValues)
if err != nil {
// failed to attach disk - there will be partial resource update
log.Errorf("utilityComputeExtraDisksConfigure: failed to attach disk ID %d to Compute ID %s: %s", diskId.(int), d.Id(), err)
@@ -120,23 +110,21 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
}
if apiErrCount > 0 {
log.Errorf("utilityComputeExtraDisksConfigure: there were %d error(s) when managing disks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
log.Errorf("utilityComputeExtraDisksConfigure: there were %d error(s) when managing disks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
return lastSavedError
}
return nil
}
func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData, m interface{}, do_delta bool) error {
func (ctrl *ControllerCfg) utilityComputeNetworksConfigure(d *schema.ResourceData, do_delta bool) error {
// "d" is filled with data according to computeResource schema, so extra networks config is retrieved via "network" key
// If do_delta is true, this function will identify changes between new and existing specs for network and try to
// If do_delta is true, this function will identify changes between new and existing specs for network and try to
// update compute configuration accordingly
// Otherwise it will apply whatever is found in the new set of "network" right away.
// Otherwise it will apply whatever is found in the new set of "network" right away.
// Primary use of do_delta=false is when calling this function from compute Create handler.
c := m.(*controller.ControllerCfg)
old_set, new_set := d.GetChange("network")
apiErrCount := 0
@@ -149,7 +137,7 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
for _, runner := range new_set.(*schema.Set).List() {
urlValues := &url.Values{}
net_data := runner.(map[string]interface{})
net_data := runner.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("netType", net_data["net_type"].(string))
urlValues.Add("netId", fmt.Sprintf("%d", net_data["net_id"].(int)))
@@ -157,7 +145,7 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
if ipSet {
urlValues.Add("ipAddr", ipaddr.(string))
}
_, err := c.DecortAPICall(ctx, "POST", ComputeNetAttachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeNetAttachAPI, urlValues)
if err != nil {
// failed to attach network - partial resource update
apiErrCount++
@@ -166,8 +154,8 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
}
if apiErrCount > 0 {
log.Errorf("utilityComputeNetworksConfigure: there were %d error(s) when managing networks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
log.Errorf("utilityComputeNetworksConfigure: there were %d error(s) when managing networks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
return lastSavedError
}
return nil
@@ -181,11 +169,11 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
urlValues.Add("computeId", d.Id())
urlValues.Add("ipAddr", net_data["ip_address"].(string))
urlValues.Add("mac", net_data["mac"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeNetDetachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeNetDetachAPI, urlValues)
if err != nil {
// failed to detach this network - there will be partial resource update
log.Errorf("utilityComputeNetworksConfigure: failed to detach net ID %d of type %s from Compute ID %s: %s",
net_data["net_id"].(int), net_data["net_type"].(string), d.Id(), err)
log.Errorf("utilityComputeNetworksConfigure: failed to detach net ID %d of type %s from Compute ID %s: %s",
net_data["net_id"].(int), net_data["net_type"].(string), d.Id(), err)
apiErrCount++
lastSavedError = err
}
@@ -197,31 +185,31 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
urlValues := &url.Values{}
net_data := runner.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("netId", fmt.Sprintf("%d", net_data["net_id"].(int)))
urlValues.Add("netId", fmt.Sprintf("%d",net_data["net_id"].(int)))
urlValues.Add("netType", net_data["net_type"].(string))
if net_data["ip_address"].(string) != "" {
urlValues.Add("ipAddr", net_data["ip_address"].(string))
}
_, err := c.DecortAPICall(ctx, "POST", ComputeNetAttachAPI, urlValues)
_, err := ctrl.decortAPICall("POST", ComputeNetAttachAPI, urlValues)
if err != nil {
// failed to attach this network - there will be partial resource update
log.Errorf("utilityComputeNetworksConfigure: failed to attach net ID %d of type %s to Compute ID %s: %s",
net_data["net_id"].(int), net_data["net_type"].(string), d.Id(), err)
log.Errorf("utilityComputeNetworksConfigure: failed to attach net ID %d of type %s to Compute ID %s: %s",
net_data["net_id"].(int), net_data["net_type"].(string), d.Id(), err)
apiErrCount++
lastSavedError = err
}
}
if apiErrCount > 0 {
log.Errorf("utilityComputeNetworksConfigure: there were %d error(s) when managing networks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
log.Errorf("utilityComputeNetworksConfigure: there were %d error(s) when managing networks of Compute ID %s. Last error was: %s",
apiErrCount, d.Id(), lastSavedError)
return lastSavedError
}
return nil
}
func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
func utilityComputeCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate Compute by one of the following approaches:
// - if compute_id is specified - locate by compute ID
// - if compute_name is specified - locate by a combination of compute name and resource
@@ -235,7 +223,7 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
// method for resource's Exists method.
//
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with compute ID set so
@@ -256,7 +244,7 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
// compute ID is specified, try to get compute instance straight by this ID
log.Debugf("utilityComputeCheckPresence: locating compute by its ID %d", theId)
urlValues.Add("computeId", fmt.Sprintf("%d", theId))
computeFacts, err := c.DecortAPICall(ctx, "POST", ComputeGetAPI, urlValues)
computeFacts, err := controller.decortAPICall("POST", ComputeGetAPI, urlValues)
if err != nil {
return "", err
}
@@ -274,9 +262,9 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
if !argSet {
return "", fmt.Errorf("Cannot locate compute by name %s if no resource group ID is set", computeName.(string))
}
urlValues.Add("rgId", fmt.Sprintf("%d", rgId))
apiResp, err := c.DecortAPICall(ctx, "POST", RgListComputesAPI, urlValues)
apiResp, err := controller.decortAPICall("POST", RgListComputesAPI, urlValues)
if err != nil {
return "", err
}
@@ -298,7 +286,7 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
// we found the Compute we need - now get detailed information via compute/get API
cgetValues := &url.Values{}
cgetValues.Add("computeId", fmt.Sprintf("%d", item.ID))
apiResp, err = c.DecortAPICall(ctx, "POST", ComputeGetAPI, cgetValues)
apiResp, err = controller.decortAPICall("POST", ComputeGetAPI, cgetValues)
if err != nil {
return "", err
}

143
decort/utility_disk.go Normal file
View File

@@ -0,0 +1,143 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityDiskCheckPresence(d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate Disk by one of the following algorithms depending on
// the parameters passed:
// - if disk ID is specified -> by disk ID
// - if disk name is specifeid -> by disk name and either account ID or account name
//
// NOTE: disk names are not unique, so the first occurence of this name in the account will
// be returned. There is no such ambiguity when locating disk by its ID.
//
// If succeeded, it returns non empty string that contains JSON formatted facts about the disk
// as returned by disks/get API call.
// Otherwise it returns empty string and meaningful error.
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for resource's Exists method.
//
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with disk ID set so
// that Import of preexisting Disk resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
diskId, argSet := d.GetOk("disk_id")
if argSet {
theId =diskId.(int)
idSet = true
}
} else {
idSet = true
}
if idSet {
// disk ID is specified, try to get disk instance straight by this ID
log.Debugf("utilityDiskCheckPresence: locating disk by its ID %d", theId)
urlValues.Add("diskId", fmt.Sprintf("%d", theId))
diskFacts, err := controller.decortAPICall("POST", DisksGetAPI, urlValues)
if err != nil {
return "", err
}
return diskFacts, nil
}
// ID or disk_di was not set in the schema upon entering this function - rely on Disk name
// and Account ID to find the disk
diskName, argSet := d.GetOk("name")
if !argSet {
// no disk ID and no disk name - we cannot locate disk in this case
return "", fmt.Errorf("Cannot locate disk if name is empty and no disk ID specified")
}
// Valid account ID is required to locate disks
// obtain Account ID by account name - it should not be zero on success
validatedAccountId, err := utilityGetAccountIdBySchema(d, m)
if err != nil {
return "", err
}
urlValues.Add("accountId", fmt.Sprintf("%d", validatedAccountId))
diskFacts, err := controller.decortAPICall("POST", DisksListAPI, urlValues)
if err != nil {
return "", err
}
log.Debugf("utilityDiskCheckPresence: ready to unmarshal string %s", diskFacts)
disksList := DisksListResp{}
err = json.Unmarshal([]byte(diskFacts), &disksList)
if err != nil {
return "", err
}
// log.Printf("%#v", vm_list)
log.Debugf("utilityDiskCheckPresence: traversing decoded JSON of length %d", len(disksList))
for index, item := range disksList {
// need to match disk by name, return the first match
if item.Name == diskName.(string) && item.Status != "DESTROYED" {
log.Debugf("utilityDiskCheckPresence: index %d, matched disk name %q", index, item.Name)
// we found the disk we need - not get detailed information via API call to disks/get
/*
// TODO: this may not be optimal as it initiates one extra call to the DECORT controller
// in spite of the fact that we already have all required information about the disk in
// item variable
//
get_urlValues := &url.Values{}
get_urlValues.Add("diskId", fmt.Sprintf("%d", item.ID))
diskFacts, err = controller.decortAPICall("POST", DisksGetAPI, get_urlValues)
if err != nil {
return "", err
}
return diskFacts, nil
*/
reencodedItem, err := json.Marshal(item)
if err != nil {
return "", err
}
return string(reencodedItem[:]), nil
}
}
return "", nil // there should be no error if disk does not exist
}

48
decort/utility_general.go Normal file
View File

@@ -0,0 +1,48 @@
/*
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"strings"
)
func Jo2JSON(arg_str string) string {
// DECORT API historically returns response in the form of Python dictionary, which generally
// looks like JSON, but does not comply with JSON syntax.
// For Golang JSON Unmarshal to work properly we need to pre-process API response as follows:
ret_string := strings.Replace(string(arg_str), "u'", "\"", -1)
ret_string = strings.Replace(ret_string, "'", "\"", -1)
ret_string = strings.Replace(ret_string, ": False", ": false", -1)
ret_string = strings.Replace(ret_string, ": True", ": true", -1)
ret_string = strings.Replace(ret_string, "null", "\"\"", -1)
ret_string = strings.Replace(ret_string, "None", "\"\"", -1)
// fix for incorrect handling of usage info
// ret_string = strings.Replace(ret_string, "<", "\"", -1)
// ret_string = strings.Replace(ret_string, ">", "\"", -1)
return ret_string
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,45 +16,39 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package grid
package decort
import (
"context"
"encoding/json"
"errors"
"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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityGridCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Grid, error) {
func utilityGridCheckPresence(d *schema.ResourceData, m interface{}) (*Grid, error) {
grid := &Grid{}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
if gridId, ok := d.GetOk("grid_id"); ok {
urlValues.Add("gridId", strconv.Itoa(gridId.(int)))
} else {
return nil, errors.New("grid_id is required")
return nil, errors.New(fmt.Sprintf("grid_id is required"))
}
log.Debugf("utilityGridCheckPresence: load grid")
gridRaw, err := c.DecortAPICall(ctx, "POST", GridGetAPI, urlValues)
gridRaw, err := controller.decortAPICall("POST", GridGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,34 +16,27 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package grid
package decort
import (
"context"
"encoding/json"
"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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityGridListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (GridList, error) {
func utilityGridListCheckPresence(d *schema.ResourceData, m interface{}) (GridList, error) {
gridList := GridList{}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
if page, ok := d.GetOk("page"); ok {
@@ -56,7 +47,7 @@ func utilityGridListCheckPresence(ctx context.Context, d *schema.ResourceData, m
}
log.Debugf("utilityGridListCheckPresence: load grid list")
gridListRaw, err := c.DecortAPICall(ctx, "POST", GridListGetAPI, urlValues)
gridListRaw, err := controller.decortAPICall("POST", GridListGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: 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.
@@ -18,33 +16,26 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Image, error) {
c := m.(*controller.ControllerCfg)
func utilityImageCheckPresence(d *schema.ResourceData, m interface{}) (*Image, error) {
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
if (strconv.Itoa(d.Get("image_id").(int))) != "0" {
@@ -53,7 +44,7 @@ func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m in
urlValues.Add("imageId", d.Id())
}
resp, err := c.DecortAPICall(ctx, "POST", imageGetAPI, urlValues)
resp, err := controller.decortAPICall("POST", imageGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,34 +16,27 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"encoding/json"
"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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ImageList, error) {
func utilityImageListCheckPresence(d *schema.ResourceData, m interface{}) (ImageList, error) {
imageList := ImageList{}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
if sepId, ok := d.GetOk("sep_id"); ok {
@@ -63,7 +54,7 @@ func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData,
}
log.Debugf("utilityImageListCheckPresence: load image list")
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListGetAPI, urlValues)
imageListRaw, err := controller.decortAPICall("POST", imageListGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,40 +16,33 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package image
package decort
import (
"context"
"encoding/json"
"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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityImageListStacksCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ImageListStacks, error) {
func utilityImageListStacksCheckPresence(d *schema.ResourceData, m interface{}) (ImageListStacks, error) {
imageListStacks := ImageListStacks{}
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
log.Debugf("utilityImageListStacksCheckPresence: load image list")
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListStacksApi, urlValues)
imageListRaw, err := controller.decortAPICall("POST", imageListStacksApi, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,34 +16,27 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package k8s
package decort
import (
"context"
"encoding/json"
"net/url"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sRecord, error) {
c := m.(*controller.ControllerCfg)
func utilityK8sCheckPresence(d *schema.ResourceData, m interface{}) (*K8sRecord, error) {
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
resp, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues)
resp, err := controller.decortAPICall("POST", K8sGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,35 +16,28 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package k8s
package decort
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sNodeRecord, error) {
c := m.(*controller.ControllerCfg)
func utilityK8sWgCheckPresence(d *schema.ResourceData, m interface{}) (*K8sNodeRecord, error) {
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
resp, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues)
resp, err := controller.decortAPICall("POST", K8sGetAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,60 +1,65 @@
/*
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.
*/
package location
import (
"context"
"encoding/json"
"fmt"
"net/url"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
var DefaultGridID int
func UtilityLocationGetDefaultGridID(ctx context.Context, m interface{}) (int, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
log.Debug("utilityLocationGetDefaultGridID: retrieving locations list")
apiResp, err := c.DecortAPICall(ctx, "POST", LocationsListAPI, urlValues)
if err != nil {
return 0, err
}
locList := LocationsListResp{}
err = json.Unmarshal([]byte(apiResp), &locList)
if err != nil {
return 0, err
}
if len(locList) == 0 {
DefaultGridID = 0
return 0, fmt.Errorf("utilityLocationGetDefaultGridID: retrieved 0 length locations list")
}
DefaultGridID = locList[0].GridID
log.Debugf("utilityLocationGetDefaultGridID: default location GridID %d, name %s", DefaultGridID, locList[0].Name)
return DefaultGridID, nil
}
/*
Copyright (c) 2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
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.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"fmt"
"net/url"
log "github.com/sirupsen/logrus"
// "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
var DefaultGridID int
func (controller *ControllerCfg) utilityLocationGetDefaultGridID() (int, error) {
urlValues := &url.Values{}
log.Debug("utilityLocationGetDefaultGridID: retrieving locations list")
apiResp, err := controller.decortAPICall("POST", LocationsListAPI, urlValues)
if err != nil {
return 0, err
}
locList := LocationsListResp{}
err = json.Unmarshal([]byte(apiResp), &locList)
if err != nil {
return 0, err
}
if len(locList) == 0 {
DefaultGridID = 0
return 0, fmt.Errorf("utilityLocationGetDefaultGridID: retrieved 0 length locations list")
}
DefaultGridID = locList[0].GridID
log.Debugf("utilityLocationGetDefaultGridID: default location GridID %d, name %s", DefaultGridID, locList[0].Name)
return DefaultGridID, nil
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,36 +16,29 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package pfw
package decort
import (
"context"
"encoding/json"
"net/url"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityPfwCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*PfwRecord, error) {
c := m.(*controller.ControllerCfg)
func utilityPfwCheckPresence(d *schema.ResourceData, m interface{}) (*PfwRecord, error) {
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
resp, err := c.DecortAPICall(ctx, "POST", ComputePfwListAPI, urlValues)
resp, err := controller.decortAPICall("POST", ComputePfwListAPI, urlValues)
if err != nil {
return nil, err
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,35 +16,61 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package rg
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
func (ctrl *ControllerCfg) utilityResgroupConfigGet(rgid int) (*ResgroupGetResp, error) {
urlValues := &url.Values{}
urlValues.Add("rgId", fmt.Sprintf("%d", rgid))
rgFacts, err := ctrl.decortAPICall("POST", ResgroupGetAPI, urlValues)
if err != nil {
return nil, err
}
log.Debugf("utilityResgroupConfigGet: ready to unmarshal string %s", rgFacts)
model := &ResgroupGetResp{}
err = json.Unmarshal([]byte(rgFacts), model)
if err != nil {
return nil, err
}
/*
ret := &ResgroupConfig{}
ret.AccountID = model.AccountID
ret.Location = model.Location
ret.Name = model.Name
ret.ID = rgid
ret.GridID = model.GridID
ret.ExtIP = model.ExtIP // legacy field for VDC - this will eventually become obsoleted by true Resource Groups
// Quota ResgroupQuotaConfig
// Network NetworkConfig
*/
log.Debugf("utilityResgroupConfigGet: account ID %d, GridID %d, Name %s",
model.AccountID, model.GridID, model.Name)
return model, nil
}
// 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(d *schema.ResourceData, m interface{}) (string, 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
@@ -64,7 +88,7 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
// method for the Terraform resource Exists method.
//
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with RG ID set so
@@ -80,12 +104,12 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
} else {
idSet = true
}
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)
rgFacts, err := controller.decortAPICall("POST", ResgroupGetAPI, urlValues)
if err != nil {
return "", err
}
@@ -100,9 +124,13 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
// Valid account ID is required to locate a resource group
// obtain Account ID by account name - it should not be zero on success
validatedAccountId, err := utilityGetAccountIdBySchema(d, m)
if err != nil {
return "", err
}
urlValues.Add("includedeleted", "false")
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupListAPI, urlValues)
apiResp, err := controller.decortAPICall("POST", ResgroupListAPI, urlValues)
if err != nil {
return "", err
}
@@ -117,7 +145,7 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
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) {
if item.Name == rgName.(string) && item.AccountID == validatedAccountId {
log.Debugf("utilityResgroupCheckPresence: match RG name %s / ID %d, account ID %d at index %d",
item.Name, item.ID, item.AccountID, index)
@@ -126,7 +154,7 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
// 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)
apiResp, err := controller.decortAPICall("POST", ResgroupGetAPI, reqValues)
if err != nil {
return "", err
}
@@ -135,5 +163,13 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
}
}
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, d.Get("account_id").(int))
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, validatedAccountId)
}
func utilityResgroupGetDefaultGridID() (interface{}, error) {
if DefaultGridID > 0 {
return fmt.Sprintf("%d", DefaultGridID), nil
}
return "", fmt.Errorf("utilityResgroupGetDefaultGridID: invalid default Grid ID %d", DefaultGridID)
}

View File

@@ -1,8 +1,6 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Copyright (c) 2020-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Sergey Shubin, <sergey.shubin@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,35 +16,50 @@ limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
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
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package vins
package decort
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"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func (ctrl *ControllerCfg) utilityVinsConfigGet(vinsid int) (*VinsRecord, error) {
urlValues := &url.Values{}
urlValues.Add("vinsId", fmt.Sprintf("%d", vinsid))
vinsFacts, err := ctrl.decortAPICall("POST", VinsGetAPI, urlValues)
if err != nil {
return nil, err
}
log.Debugf("utilityVinsConfigGet: ready to unmarshal string %q", vinsFacts)
model := &VinsRecord{}
err = json.Unmarshal([]byte(vinsFacts), model)
if err != nil {
return nil, err
}
log.Debugf("utilityVinsConfigGet: Name %d, account name:ID %s:%d, RG Name:ID %s:%d",
model.Name, model.AccountName, model.AccountID,
model.RgName, model.RgID)
return model, nil
}
// 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) {
func utilityVinsCheckPresence(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
@@ -60,7 +73,7 @@ func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m int
// method for the Terraform resource Exists method.
//
c := m.(*controller.ControllerCfg)
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with ViNS ID set so
@@ -81,7 +94,7 @@ func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m int
// 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)
vinsFacts, err := controller.decortAPICall("POST", VinsGetAPI, urlValues)
if err != nil {
return "", err
}
@@ -112,11 +125,11 @@ func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m int
urlValues.Add("accountId", fmt.Sprintf("%d", accountId.(int)))
}
apiResp, err := c.DecortAPICall(ctx, "POST", VinsSearchAPI, urlValues)
apiResp, err := controller.decortAPICall("POST", VinsSearchAPI, urlValues)
if err != nil {
return "", err
}
// log.Debugf("%s", apiResp)
// log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %s", VinsSearchAPI)
model := VinsSearchResp{}
@@ -128,24 +141,24 @@ func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m int
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
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)
item.Name, item.ID, item.AccountID, item.RgID, index)
// element returned by API vins/search does not contain all information we may need to
// 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)
rqValues.Add("vinsId", fmt.Sprintf("%d",item.ID))
vinsGetResp, err := controller.decortAPICall("POST", VinsGetAPI, rqValues)
if err != nil {
return "", err
}
return vinsGetResp, nil
return vinsGetResp, nil
}
}

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account Data Source - decort"
page_title: "decort_account Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -15,128 +15,23 @@ description: |-
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **account_id** (Number) Unique ID of the account. If account ID is specified, then account name is ignored.
- **id** (String) The ID of this resource.
- **name** (String) Name of the account. Names are case sensitive and unique.
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_name` (String)
- `acl` (List of Object) (see [below for nested schema](#nestedatt--acl))
- `ckey` (String)
- `company` (String)
- `companyurl` (String)
- `computes` (List of Object) (see [below for nested schema](#nestedatt--computes))
- `created_by` (String)
- `created_time` (Number)
- `dc_location` (String)
- `deactivation_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `displayname` (String)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `machines` (List of Object) (see [below for nested schema](#nestedatt--machines))
- `meta` (List of String)
- `resource_limits` (List of Object) (see [below for nested schema](#nestedatt--resource_limits))
- `resources` (List of Object) (see [below for nested schema](#nestedatt--resources))
- `send_access_emails` (Boolean)
- `service_account` (Boolean)
- `status` (String)
- `updated_time` (Number)
- `version` (Number)
- `vins` (List of Number)
- `vinses` (Number)
- **status** (String) Current status of the account.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--acl"></a>
### Nested Schema for `acl`
Read-Only:
- `can_be_deleted` (Boolean)
- `explicit` (Boolean)
- `guid` (String)
- `right` (String)
- `status` (String)
- `type` (String)
- `user_group_id` (String)
<a id="nestedatt--computes"></a>
### Nested Schema for `computes`
Read-Only:
- `started` (Number)
- `stopped` (Number)
<a id="nestedatt--machines"></a>
### Nested Schema for `machines`
Read-Only:
- `halted` (Number)
- `running` (Number)
<a id="nestedatt--resource_limits"></a>
### Nested Schema for `resource_limits`
Read-Only:
- `cu_c` (Number)
- `cu_d` (Number)
- `cu_i` (Number)
- `cu_m` (Number)
- `cu_np` (Number)
- `gpu_units` (Number)
<a id="nestedatt--resources"></a>
### Nested Schema for `resources`
Read-Only:
- `current` (List of Object) (see [below for nested schema](#nestedobjatt--resources--current))
- `reserved` (List of Object) (see [below for nested schema](#nestedobjatt--resources--reserved))
<a id="nestedobjatt--resources--current"></a>
### Nested Schema for `resources.current`
Read-Only:
- `cpu` (Number)
- `disksize` (Number)
- `extips` (Number)
- `exttraffic` (Number)
- `gpu` (Number)
- `ram` (Number)
<a id="nestedobjatt--resources--reserved"></a>
### Nested Schema for `resources.reserved`
Read-Only:
- `cpu` (Number)
- `disksize` (Number)
- `extips` (Number)
- `exttraffic` (Number)
- `gpu` (Number)
- `ram` (Number)
- **default** (String)
- **read** (String)

View File

@@ -1,51 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_audits_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_audits_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `call` (String)
- `responsetime` (Number)
- `statuscode` (Number)
- `timestamp` (Number)
- `user` (String)

View File

@@ -1,66 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_computes_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_computes_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `compute_id` (Number)
- `compute_name` (String)
- `cpus` (Number)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `ram` (Number)
- `registered` (Boolean)
- `rg_id` (Number)
- `rg_name` (String)
- `status` (String)
- `tech_status` (String)
- `total_disks_size` (Number)
- `updated_by` (String)
- `updated_time` (Number)
- `user_managed` (Boolean)
- `vins_connected` (Number)

View File

@@ -1,44 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_consumed_units Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_consumed_units (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `cu_c` (Number)
- `cu_d` (Number)
- `cu_i` (Number)
- `cu_m` (Number)
- `cu_np` (Number)
- `gpu_units` (Number)
- `id` (String) The ID of this resource.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,40 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_consumed_units_by_type Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_consumed_units_by_type (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
- `cu_type` (String) cloud unit resource type
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `cu_result` (Number)
- `id` (String) The ID of this resource.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,63 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_deleted_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_deleted_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `page` (Number) Page number
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `acl` (List of Object) (see [below for nested schema](#nestedobjatt--items--acl))
- `created_time` (Number)
- `deleted_time` (Number)
- `status` (String)
- `updated_time` (Number)
<a id="nestedobjatt--items--acl"></a>
### Nested Schema for `items.acl`
Read-Only:
- `explicit` (Boolean)
- `guid` (String)
- `right` (String)
- `status` (String)
- `type` (String)
- `user_group_id` (String)

View File

@@ -1,52 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_disks_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_disks_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `disk_id` (Number)
- `disk_name` (String)
- `pool` (String)
- `sep_id` (Number)
- `size_max` (Number)
- `type` (String)

View File

@@ -1,67 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_flipgroups_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_flipgroups_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `client_type` (String)
- `conn_type` (String)
- `created_by` (String)
- `created_time` (Number)
- `default_gw` (String)
- `deleted_by` (String)
- `deleted_time` (Number)
- `desc` (String)
- `fg_id` (Number)
- `fg_name` (String)
- `gid` (Number)
- `guid` (Number)
- `ip` (String)
- `milestones` (Number)
- `net_id` (Number)
- `net_type` (String)
- `netmask` (Number)
- `status` (String)
- `updated_by` (String)
- `updated_time` (Number)

View File

@@ -1,63 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `page` (Number) Page number
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `acl` (List of Object) (see [below for nested schema](#nestedobjatt--items--acl))
- `created_time` (Number)
- `deleted_time` (Number)
- `status` (String)
- `updated_time` (Number)
<a id="nestedobjatt--items--acl"></a>
### Nested Schema for `items.acl`
Read-Only:
- `explicit` (Boolean)
- `guid` (String)
- `right` (String)
- `status` (String)
- `type` (String)
- `user_group_id` (String)

View File

@@ -1,44 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_reserved_units Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_reserved_units (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `cu_c` (Number)
- `cu_d` (Number)
- `cu_i` (Number)
- `cu_m` (Number)
- `cu_np` (Number)
- `gpu_units` (Number)
- `id` (String) The ID of this resource.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,115 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_rg_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_rg_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `computes` (List of Object) (see [below for nested schema](#nestedobjatt--items--computes))
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `milestones` (Number)
- `resources` (List of Object) (see [below for nested schema](#nestedobjatt--items--resources))
- `rg_id` (Number)
- `rg_name` (String)
- `status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vinses` (Number)
<a id="nestedobjatt--items--computes"></a>
### Nested Schema for `items.computes`
Read-Only:
- `started` (Number)
- `stopped` (Number)
<a id="nestedobjatt--items--resources"></a>
### Nested Schema for `items.resources`
Read-Only:
- `consumed` (List of Object) (see [below for nested schema](#nestedobjatt--items--resources--consumed))
- `limits` (List of Object) (see [below for nested schema](#nestedobjatt--items--resources--limits))
- `reserved` (List of Object) (see [below for nested schema](#nestedobjatt--items--resources--reserved))
<a id="nestedobjatt--items--resources--consumed"></a>
### Nested Schema for `items.resources.consumed`
Read-Only:
- `cpu` (Number)
- `disksize` (Number)
- `extips` (Number)
- `exttraffic` (Number)
- `gpu` (Number)
- `ram` (Number)
<a id="nestedobjatt--items--resources--limits"></a>
### Nested Schema for `items.resources.limits`
Read-Only:
- `cpu` (Number)
- `disksize` (Number)
- `extips` (Number)
- `exttraffic` (Number)
- `gpu` (Number)
- `ram` (Number)
<a id="nestedobjatt--items--resources--reserved"></a>
### Nested Schema for `items.resources.reserved`
Read-Only:
- `cpu` (Number)
- `disksize` (Number)
- `extips` (Number)
- `exttraffic` (Number)
- `gpu` (Number)
- `ram` (Number)

View File

@@ -1,56 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_templates_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_templates_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `desc` (String)
- `public` (Boolean)
- `size` (Number)
- `status` (String)
- `template_id` (Number)
- `template_name` (String)
- `type` (String)
- `unc_path` (String)
- `username` (String)

View File

@@ -1,63 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_account_vins_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_account_vins_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) ID of the account
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Search Result (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `computes` (Number)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `external_ip` (String)
- `network` (String)
- `pri_vnf_dev_id` (Number)
- `rg_id` (Number)
- `rg_name` (String)
- `status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vin_id` (Number)
- `vin_name` (String)

View File

@@ -1,90 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_bservice Data Source - decort"
subcategory: ""
description: |-
---
# decort_bservice (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `service_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_id` (Number)
- `account_name` (String)
- `base_domain` (String)
- `computes` (List of Object) (see [below for nested schema](#nestedatt--computes))
- `cpu_total` (Number)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `disk_total` (String)
- `gid` (Number)
- `groups` (List of Number)
- `groups_name` (List of String)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `milestones` (Number)
- `parent_srv_id` (Number)
- `parent_srv_type` (String)
- `ram_total` (Number)
- `rg_id` (Number)
- `rg_name` (String)
- `service_name` (String)
- `snapshots` (List of Object) (see [below for nested schema](#nestedatt--snapshots))
- `ssh_key` (String)
- `ssh_user` (String)
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `user_managed` (Boolean)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--computes"></a>
### Nested Schema for `computes`
Read-Only:
- `compgroup_id` (Number)
- `compgroup_name` (String)
- `compgroup_role` (String)
- `id` (Number)
- `name` (String)
<a id="nestedatt--snapshots"></a>
### Nested Schema for `snapshots`
Read-Only:
- `guid` (String)
- `label` (String)
- `timestamp` (Number)
- `valid` (Boolean)

View File

@@ -1,68 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_bservice_deleted_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_bservice_deleted_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `account_id` (Number) ID of the account to query for BasicService instances
- `page` (Number) Page number
- `rg_id` (Number) ID of the resource group to query for BasicService instances
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `base_domain` (String)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `gid` (Number)
- `groups` (List of Number)
- `guid` (Number)
- `parent_srv_id` (Number)
- `parent_srv_type` (String)
- `rg_id` (Number)
- `rg_name` (String)
- `service_id` (Number)
- `service_name` (String)
- `ssh_user` (String)
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `user_managed` (Boolean)

View File

@@ -1,88 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_bservice_group Data Source - decort"
subcategory: ""
description: |-
---
# decort_bservice_group (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `compgroup_id` (Number)
- `service_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_id` (Number)
- `account_name` (String)
- `compgroup_name` (String)
- `computes` (List of Object) (see [below for nested schema](#nestedatt--computes))
- `consistency` (Boolean)
- `cpu` (Number)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `disk` (Number)
- `driver` (String)
- `extnets` (List of Number)
- `gid` (Number)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `image_id` (Number)
- `milestones` (Number)
- `parents` (List of Number)
- `ram` (Number)
- `rg_id` (Number)
- `rg_name` (String)
- `role` (String)
- `sep_id` (Number)
- `seq_no` (Number)
- `status` (String)
- `tech_status` (String)
- `timeout_start` (Number)
- `updated_by` (String)
- `updated_time` (Number)
- `vinses` (List of Number)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--computes"></a>
### Nested Schema for `computes`
Read-Only:
- `id` (Number)
- `ip_addresses` (List of String)
- `name` (String)
- `os_users` (List of Object) (see [below for nested schema](#nestedobjatt--computes--os_users))
<a id="nestedobjatt--computes--os_users"></a>
### Nested Schema for `computes.os_users`
Read-Only:
- `login` (String)
- `password` (String)

View File

@@ -1,68 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_bservice_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_bservice_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `account_id` (Number) ID of the account to query for BasicService instances
- `page` (Number) Page number
- `rg_id` (Number) ID of the resource group to query for BasicService instances
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `base_domain` (String)
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `gid` (Number)
- `groups` (List of Number)
- `guid` (Number)
- `parent_srv_id` (Number)
- `parent_srv_type` (String)
- `rg_id` (Number)
- `rg_name` (String)
- `service_id` (Number)
- `service_name` (String)
- `ssh_user` (String)
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `user_managed` (Boolean)

View File

@@ -1,50 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_bservice_snapshot_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_bservice_snapshot_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `service_id` (Number) ID of the BasicService instance
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `guid` (String)
- `label` (String)
- `timestamp` (Number)
- `valid` (Boolean)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_disk Data Source - decort"
page_title: "decort_disk Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -15,100 +15,31 @@ description: |-
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `disk_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **account_id** (Number) ID of the account this disk belongs to. If disk ID is specified, then account ID is ignored.
- **disk_id** (Number) ID of the disk to get. If disk ID is specified, then disk name and account ID are ignored.
- **id** (String) The ID of this resource.
- **name** (String) Name of this disk. NOTE: disk names are NOT unique within an account. If disk ID is specified, disk name is ignored.
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_id` (Number)
- `account_name` (String)
- `acl` (String)
- `boot_partition` (Number)
- `compute_id` (Number)
- `compute_name` (String)
- `created_time` (Number)
- `deleted_time` (Number)
- `desc` (String)
- `destruction_time` (Number)
- `devicename` (String)
- `disk_name` (String)
- `disk_path` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `image_id` (Number)
- `images` (List of String)
- `iotune` (List of Object) (see [below for nested schema](#nestedatt--iotune))
- `iqn` (String)
- `login` (String)
- `milestones` (Number)
- `order` (Number)
- `params` (String)
- `parent_id` (Number)
- `passwd` (String)
- `pci_slot` (Number)
- `pool` (String)
- `purge_attempts` (Number)
- `purge_time` (Number)
- `reality_device_number` (Number)
- `reference_id` (String)
- `res_id` (String)
- `res_name` (String)
- `role` (String)
- `sep_id` (Number)
- `sep_type` (String)
- `size_max` (Number)
- `size_used` (Number)
- `snapshots` (List of Object) (see [below for nested schema](#nestedatt--snapshots))
- `status` (String)
- `tech_status` (String)
- `type` (String)
- `vmid` (Number)
- **account_name** (String) Name of the account this disk belongs to. If account ID is specified, account name is ignored.
- **description** (String) User-defined text description of this disk.
- **image_id** (Number) ID of the image, which this disk was cloned from (valid for disk clones only).
- **pool** (String) Pool where this disk is located.
- **sep_id** (Number) Storage end-point provider serving this disk.
- **sep_type** (String) Type of the storage end-point provider serving this disk.
- **size** (Number) Size of the disk in GB.
- **type** (String) Type of this disk. E.g. D for data disks, B for boot.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--iotune"></a>
### Nested Schema for `iotune`
Read-Only:
- `read_bytes_sec` (Number)
- `read_bytes_sec_max` (Number)
- `read_iops_sec` (Number)
- `read_iops_sec_max` (Number)
- `size_iops_sec` (Number)
- `total_bytes_sec` (Number)
- `total_bytes_sec_max` (Number)
- `total_iops_sec` (Number)
- `total_iops_sec_max` (Number)
- `write_bytes_sec` (Number)
- `write_bytes_sec_max` (Number)
- `write_iops_sec` (Number)
- `write_iops_sec_max` (Number)
<a id="nestedatt--snapshots"></a>
### Nested Schema for `snapshots`
Read-Only:
- `guid` (String)
- `label` (String)
- `res_id` (String)
- `snap_set_guid` (String)
- `snap_set_time` (Number)
- `timestamp` (Number)
- **default** (String)
- **read** (String)

View File

@@ -1,124 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_disk_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_disk_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `account_id` (Number) ID of the account the disks belong to
- `page` (Number) Page number
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- `type` (String) type of the disks
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `acl` (String)
- `boot_partition` (Number)
- `compute_id` (Number)
- `compute_name` (String)
- `created_time` (Number)
- `deleted_time` (Number)
- `desc` (String)
- `destruction_time` (Number)
- `devicename` (String)
- `disk_id` (Number)
- `disk_name` (String)
- `disk_path` (String)
- `gid` (Number)
- `guid` (Number)
- `image_id` (Number)
- `images` (List of String)
- `iotune` (List of Object) (see [below for nested schema](#nestedobjatt--items--iotune))
- `iqn` (String)
- `login` (String)
- `machine_id` (Number)
- `machine_name` (String)
- `milestones` (Number)
- `order` (Number)
- `params` (String)
- `parent_id` (Number)
- `passwd` (String)
- `pci_slot` (Number)
- `pool` (String)
- `purge_attempts` (Number)
- `purge_time` (Number)
- `reality_device_number` (Number)
- `reference_id` (String)
- `res_id` (String)
- `res_name` (String)
- `role` (String)
- `sep_id` (Number)
- `sep_type` (String)
- `size_max` (Number)
- `size_used` (Number)
- `snapshots` (List of Object) (see [below for nested schema](#nestedobjatt--items--snapshots))
- `status` (String)
- `tech_status` (String)
- `type` (String)
- `vmid` (Number)
<a id="nestedobjatt--items--iotune"></a>
### Nested Schema for `items.iotune`
Read-Only:
- `read_bytes_sec` (Number)
- `read_bytes_sec_max` (Number)
- `read_iops_sec` (Number)
- `read_iops_sec_max` (Number)
- `size_iops_sec` (Number)
- `total_bytes_sec` (Number)
- `total_bytes_sec_max` (Number)
- `total_iops_sec` (Number)
- `total_iops_sec_max` (Number)
- `write_bytes_sec` (Number)
- `write_bytes_sec_max` (Number)
- `write_iops_sec` (Number)
- `write_iops_sec_max` (Number)
<a id="nestedobjatt--items--snapshots"></a>
### Nested Schema for `items.snapshots`
Read-Only:
- `guid` (String)
- `label` (String)
- `res_id` (String)
- `snap_set_guid` (String)
- `snap_set_time` (Number)
- `timestamp` (Number)

View File

@@ -1,98 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_extnet Data Source - decort"
subcategory: ""
description: |-
---
# decort_extnet (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `net_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `check__ips` (List of String)
- `check_ips` (List of String)
- `ckey` (String)
- `default` (Boolean)
- `default_qos` (List of Object) (see [below for nested schema](#nestedatt--default_qos))
- `desc` (String)
- `dns` (List of String)
- `excluded` (List of String)
- `free_ips` (Number)
- `gateway` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `ipcidr` (String)
- `meta` (List of String) meta
- `milestones` (Number)
- `net_name` (String)
- `network` (String)
- `network_id` (Number)
- `pre_reservations_num` (Number)
- `prefix` (Number)
- `pri_vnf_dev_id` (Number)
- `reservations` (List of Object) (see [below for nested schema](#nestedatt--reservations))
- `shared_with` (List of Number)
- `status` (String)
- `vlan_id` (Number)
- `vnfs` (List of Object) (see [below for nested schema](#nestedatt--vnfs))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--default_qos"></a>
### Nested Schema for `default_qos`
Read-Only:
- `e_rate` (Number)
- `guid` (String)
- `in_burst` (Number)
- `in_rate` (Number)
<a id="nestedatt--reservations"></a>
### Nested Schema for `reservations`
Read-Only:
- `client_type` (String)
- `desc` (String)
- `domainname` (String)
- `hostname` (String)
- `ip` (String)
- `mac` (String)
- `type` (String)
- `vm_id` (Number)
<a id="nestedatt--vnfs"></a>
### Nested Schema for `vnfs`
Read-Only:
- `dhcp` (Number)

View File

@@ -1,63 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_extnet_computes_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_extnet_computes_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `account_id` (Number) filter by account ID
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `extnets` (List of Object) (see [below for nested schema](#nestedobjatt--items--extnets))
- `id` (Number)
- `name` (String)
- `rg_id` (Number)
- `rg_name` (String)
<a id="nestedobjatt--items--extnets"></a>
### Nested Schema for `items.extnets`
Read-Only:
- `ipaddr` (String)
- `ipcidr` (String)
- `name` (String)
- `net_id` (Number)

View File

@@ -1,35 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_extnet_default Data Source - decort"
subcategory: ""
description: |-
---
# decort_extnet_default (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `net_id` (Number)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,48 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_extnet_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_extnet_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `account_id` (Number) filter by account ID
- `page` (Number) Page number
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `ipcidr` (String)
- `name` (String)
- `net_id` (Number)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_grid Data Source - decort"
page_title: "decort_grid Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,27 +17,27 @@ description: |-
### Required
- `grid_id` (Number)
- **grid_id** (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `flag` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (Number) The ID of this resource.
- `location_code` (String)
- `name` (String)
- **flag** (String)
- **gid** (Number)
- **guid** (Number)
- **id** (Number) The ID of this resource.
- **location_code** (String)
- **name** (String)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_grid_list Data Source - decort"
page_title: "decort_grid_list Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,22 +17,22 @@ description: |-
### Optional
- `page` (Number) page number
- `size` (Number) page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **id** (String) The ID of this resource.
- **page** (Number) page number
- **size** (Number) page size
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) grid list (see [below for nested schema](#nestedatt--items))
- **items** (List of Object) grid list (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--items"></a>
@@ -40,11 +40,11 @@ Optional:
Read-Only:
- `flag` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (Number)
- `location_code` (String)
- `name` (String)
- **flag** (String)
- **gid** (Number)
- **guid** (Number)
- **id** (Number)
- **location_code** (String)
- **name** (String)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_image Data Source - decort"
page_title: "decort_image Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,58 +17,61 @@ description: |-
### Required
- `image_id` (Number)
- **image_id** (Number) image id
### Optional
- `show_all` (Boolean)
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **id** (String) The ID of this resource.
- **shared_with** (List of Number)
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_id` (Number)
- `acl` (String)
- `architecture` (String)
- `boot_type` (String)
- `bootable` (Boolean)
- `ckey` (String)
- `compute_ci_id` (Number)
- `deleted_time` (String)
- `desc` (String)
- `drivers` (List of String)
- `enabled` (Boolean)
- `gid` (Number)
- `guid` (Number)
- `history` (List of Object) (see [below for nested schema](#nestedatt--history))
- `hot_resize` (Boolean)
- `id` (String) The ID of this resource.
- `image_name` (String)
- `last_modified` (Number)
- `link_to` (Number)
- `milestones` (Number)
- `password` (String)
- `pool_name` (String)
- `provider_name` (String)
- `purge_attempts` (Number)
- `res_id` (String)
- `rescuecd` (Boolean)
- `sep_id` (Number)
- `shared_with` (List of Number)
- `size` (Number)
- `status` (String)
- `tech_status` (String)
- `type` (String)
- `unc_path` (String)
- `username` (String)
- `version` (String)
- **account_id** (Number) AccountId to make the image exclusive
- **architecture** (String) binary architecture of this image, one of X86_64 of PPC64_LE
- **boot_type** (String) Boot type of image bios or uefi
- **bootable** (Boolean) Does this image boot OS
- **computeci_id** (Number)
- **desc** (String)
- **drivers** (List of String) List of types of compute suitable for image. Example: [ "KVM_X86" ]
- **enabled** (Boolean)
- **gid** (Number) grid (platform) ID where this template should be create in
- **guid** (Number)
- **history** (List of Object) (see [below for nested schema](#nestedatt--history))
- **hot_resize** (Boolean) Does this machine supports hot resize
- **image_type** (String) Image type linux, windows or other
- **last_modified** (Number)
- **link_to** (Number)
- **meta** (List of String) meta
- **milestones** (Number)
- **name** (String) Name of the rescue disk
- **password** (String) Optional password for the image
- **password_dl** (String) password for upload binary media
- **permanently** (Boolean) Whether to completely delete the image
- **pool_name** (String) pool for image create
- **provider_name** (String)
- **purge_attempts** (Number)
- **reference_id** (String)
- **res_id** (String)
- **res_name** (String)
- **rescuecd** (Boolean)
- **sep_id** (Number) storage endpoint provider ID
- **size** (Number) image size
- **status** (String) status
- **tech_status** (String) tech atatus
- **unc_path** (String) unc path
- **url** (String) URL where to download media from
- **username** (String) Optional username for the image
- **username_dl** (String) username for upload binary media
- **version** (String) version
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--history"></a>
@@ -76,8 +79,8 @@ Optional:
Read-Only:
- `guid` (String)
- `id` (Number)
- `timestamp` (Number)
- **guid** (String)
- **id** (Number)
- **timestamp** (Number)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_image_list Data Source - decort"
page_title: "decort_image_list Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,23 +17,24 @@ description: |-
### Optional
- `account_id` (Number) optional account ID to include account images
- `page` (Number) page number
- `size` (Number) page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **id** (String) The ID of this resource.
- **page** (Number) page number
- **sep_id** (Number) filter images by storage endpoint provider ID
- **shared_with** (Number) filter images by account ID availability
- **size** (Number) page size
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) image list (see [below for nested schema](#nestedatt--items))
- **items** (List of Object) image list (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--items"></a>
@@ -41,23 +42,53 @@ Optional:
Read-Only:
- `account_id` (Number)
- `architecture` (String)
- `boot_type` (String)
- `bootable` (Boolean)
- `cdrom` (Boolean)
- `desc` (String)
- `drivers` (List of String)
- `hot_resize` (Boolean)
- `image_id` (Number)
- `image_name` (String)
- `link_to` (Number)
- `pool_name` (String)
- `sep_id` (Number)
- `size` (Number)
- `status` (String)
- `type` (String)
- `username` (String)
- `virtual` (Boolean)
- **account_id** (Number)
- **architecture** (String)
- **boot_type** (String)
- **bootable** (Boolean)
- **computeci_id** (Number)
- **desc** (String)
- **drivers** (List of String)
- **enabled** (Boolean)
- **gid** (Number)
- **guid** (Number)
- **history** (List of Object) (see [below for nested schema](#nestedobjatt--items--history))
- **hot_resize** (Boolean)
- **image_id** (Number)
- **image_type** (String)
- **last_modified** (Number)
- **link_to** (Number)
- **meta** (List of String)
- **milestones** (Number)
- **name** (String)
- **password** (String)
- **password_dl** (String)
- **permanently** (Boolean)
- **pool_name** (String)
- **provider_name** (String)
- **purge_attempts** (Number)
- **reference_id** (String)
- **res_id** (String)
- **res_name** (String)
- **rescuecd** (Boolean)
- **sep_id** (Number)
- **shared_with** (List of Number)
- **size** (Number)
- **status** (String)
- **tech_status** (String)
- **unc_path** (String)
- **url** (String)
- **username** (String)
- **username_dl** (String)
- **version** (String)
<a id="nestedobjatt--items--history"></a>
### Nested Schema for `items.history`
Read-Only:
- **guid** (String)
- **id** (Number)
- **timestamp** (Number)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_image_list_stacks Data Source - decort"
page_title: "decort_image_list_stacks Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,26 +17,26 @@ description: |-
### Required
- `image_id` (Number) image id
- **image_id** (Number) image id
### Optional
- `page` (Number) page number
- `size` (Number) page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **id** (String) The ID of this resource.
- **page** (Number) page number
- **size** (Number) page size
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) items of stacks list (see [below for nested schema](#nestedatt--items))
- **items** (List of Object) items of stacks list (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--items"></a>
@@ -44,20 +44,20 @@ Optional:
Read-Only:
- `api_key` (String)
- `api_url` (String)
- `app_id` (String)
- `desc` (String)
- `drivers` (List of String)
- `error` (Number)
- `guid` (Number)
- `id` (Number)
- `images` (List of Number)
- `login` (String)
- `name` (String)
- `passwd` (String)
- `reference_id` (String)
- `status` (String)
- `type` (String)
- **api_key** (String)
- **api_url** (String)
- **app_id** (String)
- **desc** (String)
- **drivers** (List of String)
- **error** (Number)
- **guid** (Number)
- **id** (Number)
- **images** (List of Number)
- **login** (String)
- **name** (String)
- **passwd** (String)
- **reference_id** (String)
- **status** (String)
- **type** (String)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_kvmvm Data Source - decort"
page_title: "decort_kvmvm Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,46 +17,46 @@ description: |-
### Optional
- `compute_id` (Number) ID of the compute instance. If ID is specified, name and resource group ID are ignored.
- `name` (String) Name of this compute instance. NOTE: this parameter is case sensitive.
- `network` (Block Set, Max: 8) Network connection(s) for this compute. (see [below for nested schema](#nestedblock--network))
- `rg_id` (Number) ID of the resource group where this compute instance is located.
- `started` (Boolean) Is compute started.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **compute_id** (Number) ID of the compute instance. If ID is specified, name and resource group ID are ignored.
- **id** (String) The ID of this resource.
- **name** (String) Name of this compute instance. NOTE: this parameter is case sensitive.
- **network** (Block Set, Max: 8) Network connection(s) for this compute. (see [below for nested schema](#nestedblock--network))
- **rg_id** (Number) ID of the resource group where this compute instance is located.
- **started** (Boolean) Is compute started.
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_id` (Number) ID of the account this compute instance belongs to.
- `account_name` (String) Name of the account this compute instance belongs to.
- `boot_disk_id` (Number) This compute instance boot disk ID.
- `boot_disk_size` (Number) This compute instance boot disk size in GB.
- `cloud_init` (String) Placeholder for cloud_init parameters.
- `cpu` (Number) Number of CPUs allocated for this compute instance.
- `description` (String) User-defined text description of this compute instance.
- `driver` (String) Hardware architecture of this compute instance.
- `extra_disks` (Set of Number) IDs of the extra disk(s) attached to this compute.
- `id` (String) The ID of this resource.
- `image_id` (Number) ID of the OS image this compute instance is based on.
- `image_name` (String) Name of the OS image this compute instance is based on.
- `os_users` (List of Object) Guest OS users provisioned on this compute instance. (see [below for nested schema](#nestedatt--os_users))
- `ram` (Number) Amount of RAM in MB allocated for this compute instance.
- `rg_name` (String) Name of the resource group where this compute instance is located.
- **account_id** (Number) ID of the account this compute instance belongs to.
- **account_name** (String) Name of the account this compute instance belongs to.
- **boot_disk_id** (Number) This compute instance boot disk ID.
- **boot_disk_size** (Number) This compute instance boot disk size in GB.
- **cloud_init** (String) Placeholder for cloud_init parameters.
- **cpu** (Number) Number of CPUs allocated for this compute instance.
- **description** (String) User-defined text description of this compute instance.
- **driver** (String) Hardware architecture of this compute instance.
- **extra_disks** (Set of Number) IDs of the extra disk(s) attached to this compute.
- **image_id** (Number) ID of the OS image this compute instance is based on.
- **image_name** (String) Name of the OS image this compute instance is based on.
- **os_users** (List of Object) Guest OS users provisioned on this compute instance. (see [below for nested schema](#nestedatt--os_users))
- **ram** (Number) Amount of RAM in MB allocated for this compute instance.
- **rg_name** (String) Name of the resource group where this compute instance is located.
<a id="nestedblock--network"></a>
### Nested Schema for `network`
Required:
- `net_id` (Number) ID of the network for this connection.
- `net_type` (String) Type of the network for this connection, either EXTNET or VINS.
- **net_id** (Number) ID of the network for this connection.
- **net_type** (String) Type of the network for this connection, either EXTNET or VINS.
Optional:
- `ip_address` (String) Optional IP address to assign to this connection. This IP should belong to the selected network and free for use.
- **ip_address** (String) Optional IP address to assign to this connection. This IP should belong to the selected network and free for use.
Read-Only:
- `mac` (String) MAC address associated with this connection. MAC address is assigned automatically.
- **mac** (String) MAC address associated with this connection. MAC address is assigned automatically.
<a id="nestedblock--timeouts"></a>
@@ -64,8 +64,8 @@ Read-Only:
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--os_users"></a>
@@ -73,9 +73,9 @@ Optional:
Read-Only:
- `guid` (String)
- `login` (String)
- `password` (String)
- `public_key` (String)
- **guid** (String)
- **login** (String)
- **password** (String)
- **public_key** (String)

View File

@@ -1,167 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_lb Data Source - decort"
subcategory: ""
description: |-
---
# decort_lb (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `lb_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `backends` (List of Object) (see [below for nested schema](#nestedatt--backends))
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `desc` (String)
- `dp_api_user` (String)
- `extnet_id` (Number)
- `frontends` (List of Object) (see [below for nested schema](#nestedatt--frontends))
- `gid` (Number)
- `guid` (Number)
- `ha_mode` (Boolean)
- `id` (String) The ID of this resource.
- `image_id` (Number)
- `milestones` (Number)
- `name` (String)
- `primary_node` (List of Object) (see [below for nested schema](#nestedatt--primary_node))
- `rg_id` (Number)
- `rg_name` (String)
- `secondary_node` (List of Object) (see [below for nested schema](#nestedatt--secondary_node))
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vins_id` (Number)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--backends"></a>
### Nested Schema for `backends`
Read-Only:
- `algorithm` (String)
- `guid` (String)
- `name` (String)
- `server_default_settings` (List of Object) (see [below for nested schema](#nestedobjatt--backends--server_default_settings))
- `servers` (List of Object) (see [below for nested schema](#nestedobjatt--backends--servers))
<a id="nestedobjatt--backends--server_default_settings"></a>
### Nested Schema for `backends.server_default_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedobjatt--backends--servers"></a>
### Nested Schema for `backends.servers`
Read-Only:
- `address` (String)
- `check` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
- `server_settings` (List of Object) (see [below for nested schema](#nestedobjatt--backends--servers--server_settings))
<a id="nestedobjatt--backends--servers--server_settings"></a>
### Nested Schema for `backends.servers.server_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedatt--frontends"></a>
### Nested Schema for `frontends`
Read-Only:
- `backend` (String)
- `bindings` (List of Object) (see [below for nested schema](#nestedobjatt--frontends--bindings))
- `guid` (String)
- `name` (String)
<a id="nestedobjatt--frontends--bindings"></a>
### Nested Schema for `frontends.bindings`
Read-Only:
- `address` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
<a id="nestedatt--primary_node"></a>
### Nested Schema for `primary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)
<a id="nestedatt--secondary_node"></a>
### Nested Schema for `secondary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)

View File

@@ -1,175 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_lb_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_lb_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `includedeleted` (Boolean)
- `page` (Number)
- `size` (Number)
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `backends` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends))
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `desc` (String)
- `dp_api_password` (String)
- `dp_api_user` (String)
- `extnet_id` (Number)
- `frontends` (List of Object) (see [below for nested schema](#nestedobjatt--items--frontends))
- `gid` (Number)
- `guid` (Number)
- `ha_mode` (Boolean)
- `image_id` (Number)
- `lb_id` (Number)
- `milestones` (Number)
- `name` (String)
- `primary_node` (List of Object) (see [below for nested schema](#nestedobjatt--items--primary_node))
- `rg_id` (Number)
- `rg_name` (String)
- `secondary_node` (List of Object) (see [below for nested schema](#nestedobjatt--items--secondary_node))
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vins_id` (Number)
<a id="nestedobjatt--items--backends"></a>
### Nested Schema for `items.backends`
Read-Only:
- `algorithm` (String)
- `guid` (String)
- `name` (String)
- `server_default_settings` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--server_default_settings))
- `servers` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--servers))
<a id="nestedobjatt--items--backends--server_default_settings"></a>
### Nested Schema for `items.backends.server_default_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedobjatt--items--backends--servers"></a>
### Nested Schema for `items.backends.servers`
Read-Only:
- `address` (String)
- `check` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
- `server_settings` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--servers--server_settings))
<a id="nestedobjatt--items--backends--servers--server_settings"></a>
### Nested Schema for `items.backends.servers.server_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedobjatt--items--frontends"></a>
### Nested Schema for `items.frontends`
Read-Only:
- `backend` (String)
- `bindings` (List of Object) (see [below for nested schema](#nestedobjatt--items--frontends--bindings))
- `guid` (String)
- `name` (String)
<a id="nestedobjatt--items--frontends--bindings"></a>
### Nested Schema for `items.frontends.bindings`
Read-Only:
- `address` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
<a id="nestedobjatt--items--primary_node"></a>
### Nested Schema for `items.primary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)
<a id="nestedobjatt--items--secondary_node"></a>
### Nested Schema for `items.secondary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)

View File

@@ -1,174 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_lb_list_deleted Data Source - decort"
subcategory: ""
description: |-
---
# decort_lb_list_deleted (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `page` (Number)
- `size` (Number)
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `backends` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends))
- `created_by` (String)
- `created_time` (Number)
- `deleted_by` (String)
- `deleted_time` (Number)
- `desc` (String)
- `dp_api_password` (String)
- `dp_api_user` (String)
- `extnet_id` (Number)
- `frontends` (List of Object) (see [below for nested schema](#nestedobjatt--items--frontends))
- `gid` (Number)
- `guid` (Number)
- `ha_mode` (Boolean)
- `image_id` (Number)
- `lb_id` (Number)
- `milestones` (Number)
- `name` (String)
- `primary_node` (List of Object) (see [below for nested schema](#nestedobjatt--items--primary_node))
- `rg_id` (Number)
- `rg_name` (String)
- `secondary_node` (List of Object) (see [below for nested schema](#nestedobjatt--items--secondary_node))
- `status` (String)
- `tech_status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vins_id` (Number)
<a id="nestedobjatt--items--backends"></a>
### Nested Schema for `items.backends`
Read-Only:
- `algorithm` (String)
- `guid` (String)
- `name` (String)
- `server_default_settings` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--server_default_settings))
- `servers` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--servers))
<a id="nestedobjatt--items--backends--server_default_settings"></a>
### Nested Schema for `items.backends.server_default_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedobjatt--items--backends--servers"></a>
### Nested Schema for `items.backends.servers`
Read-Only:
- `address` (String)
- `check` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
- `server_settings` (List of Object) (see [below for nested schema](#nestedobjatt--items--backends--servers--server_settings))
<a id="nestedobjatt--items--backends--servers--server_settings"></a>
### Nested Schema for `items.backends.servers.server_settings`
Read-Only:
- `downinter` (Number)
- `fall` (Number)
- `guid` (String)
- `inter` (Number)
- `maxconn` (Number)
- `maxqueue` (Number)
- `rise` (Number)
- `slowstart` (Number)
- `weight` (Number)
<a id="nestedobjatt--items--frontends"></a>
### Nested Schema for `items.frontends`
Read-Only:
- `backend` (String)
- `bindings` (List of Object) (see [below for nested schema](#nestedobjatt--items--frontends--bindings))
- `guid` (String)
- `name` (String)
<a id="nestedobjatt--items--frontends--bindings"></a>
### Nested Schema for `items.frontends.bindings`
Read-Only:
- `address` (String)
- `guid` (String)
- `name` (String)
- `port` (Number)
<a id="nestedobjatt--items--primary_node"></a>
### Nested Schema for `items.primary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)
<a id="nestedobjatt--items--secondary_node"></a>
### Nested Schema for `items.secondary_node`
Read-Only:
- `backend_ip` (String)
- `compute_id` (Number)
- `frontend_ip` (String)
- `guid` (String)
- `mgmt_ip` (String)
- `network_id` (Number)

View File

@@ -1,35 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_location_url Data Source - decort"
subcategory: ""
description: |-
---
# decort_location_url (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `url` (String) Location url
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,52 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_locations_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_locations_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `page` (Number) page number
- `size` (Number) page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) Locations list (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `ckey` (String)
- `flag` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (Number)
- `location_code` (String)
- `meta` (List of String)
- `name` (String)

View File

@@ -1,49 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_pcidevice Data Source - decort"
subcategory: ""
description: |-
---
# decort_pcidevice (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `device_id` (Number)
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `ckey` (String)
- `compute_id` (Number)
- `description` (String)
- `guid` (Number)
- `hw_path` (String)
- `id` (String) The ID of this resource.
- `meta` (List of String)
- `name` (String)
- `rg_id` (Number)
- `stack_id` (Number)
- `status` (String)
- `system_name` (String)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,54 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_pcidevice_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_pcidevice_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) pcidevice list (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `ckey` (String)
- `compute_id` (Number)
- `description` (String)
- `device_id` (Number)
- `guid` (Number)
- `hw_path` (String)
- `meta` (List of String)
- `name` (String)
- `rg_id` (Number)
- `stack_id` (Number)
- `status` (String)
- `system_name` (String)

View File

@@ -1,6 +1,6 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_resgroup Data Source - decort"
page_title: "decort_resgroup Data Source - terraform-provider-decort"
subcategory: ""
description: |-
@@ -17,30 +17,30 @@ description: |-
### Required
- `account_id` (Number) Unique ID of the account, which this resource group belongs to.
- **account_id** (Number) Unique ID of the account, which this resource group belongs to.
### Optional
- `name` (String) Name of the resource group. Names are case sensitive and unique within the context of an account.
- `rg_id` (Number) Unique ID of the resource group. If this ID is specified, then resource group name is ignored.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- **id** (String) The ID of this resource.
- **name** (String) Name of the resource group. Names are case sensitive and unique within the context of an account.
- **rg_id** (Number) Unique ID of the resource group. If this ID is specified, then resource group name is ignored.
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `account_name` (String) Name of the account, which this resource group belongs to.
- `def_net_id` (Number) ID of the default network for this resource group (if any).
- `def_net_type` (String) Type of the default network for this resource group.
- `description` (String) User-defined text description of this resource group.
- `id` (String) The ID of this resource.
- `quota` (List of Object) Quota settings for this resource group. (see [below for nested schema](#nestedatt--quota))
- **account_name** (String) Name of the account, which this resource group belongs to.
- **def_net_id** (Number) ID of the default network for this resource group (if any).
- **def_net_type** (String) Type of the default network for this resource group.
- **description** (String) User-defined text description of this resource group.
- **quota** (List of Object) Quota settings for this resource group. (see [below for nested schema](#nestedatt--quota))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
- **default** (String)
- **read** (String)
<a id="nestedatt--quota"></a>
@@ -48,11 +48,11 @@ Optional:
Read-Only:
- `cpu` (Number)
- `disk` (Number)
- `ext_ips` (Number)
- `ext_traffic` (Number)
- `gpu_units` (Number)
- `ram` (Number)
- **cpu** (Number)
- **disk** (Number)
- **ext_ips** (Number)
- **ext_traffic** (Number)
- **gpu_units** (Number)
- **ram** (Number)

View File

@@ -1,94 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_rg_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_rg_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Optional
- `includedeleted` (Boolean) included deleted resource groups
- `page` (Number) Page number
- `size` (Number) Page size
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Object) (see [below for nested schema](#nestedatt--items))
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--items"></a>
### Nested Schema for `items`
Read-Only:
- `account_id` (Number)
- `account_name` (String)
- `acl` (List of Object) (see [below for nested schema](#nestedobjatt--items--acl))
- `created_by` (String)
- `created_time` (Number)
- `def_net_id` (Number)
- `def_net_type` (String)
- `deleted_by` (String)
- `deleted_time` (Number)
- `desc` (String)
- `gid` (Number)
- `guid` (Number)
- `lock_status` (String)
- `milestones` (Number)
- `name` (String)
- `register_computes` (Boolean)
- `resource_limits` (List of Object) (see [below for nested schema](#nestedobjatt--items--resource_limits))
- `rg_id` (Number)
- `secret` (String)
- `status` (String)
- `updated_by` (String)
- `updated_time` (Number)
- `vins` (List of Number)
- `vms` (List of Number)
<a id="nestedobjatt--items--acl"></a>
### Nested Schema for `items.acl`
Read-Only:
- `explicit` (Boolean)
- `guid` (String)
- `right` (String)
- `status` (String)
- `type` (String)
- `user_group_id` (String)
<a id="nestedobjatt--items--resource_limits"></a>
### Nested Schema for `items.resource_limits`
Read-Only:
- `cu_c` (Number)
- `cu_d` (Number)
- `cu_i` (Number)
- `cu_m` (Number)
- `cu_np` (Number)
- `gpu_units` (Number)

View File

@@ -1,51 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_sep Data Source - decort"
subcategory: ""
description: |-
---
# decort_sep (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `sep_id` (Number) sep type des id
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `ckey` (String)
- `config` (String)
- `consumed_by` (List of Number)
- `desc` (String)
- `gid` (Number)
- `guid` (Number)
- `id` (String) The ID of this resource.
- `meta` (List of String)
- `milestones` (Number)
- `name` (String)
- `obj_status` (String)
- `provided_by` (List of Number)
- `tech_status` (String)
- `type` (String)
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,39 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_sep_config Data Source - decort"
subcategory: ""
description: |-
---
# decort_sep_config (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `sep_id` (Number) storage endpoint provider ID
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `config` (String) sep config json string
- `id` (String) The ID of this resource.
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

View File

@@ -1,69 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_sep_consumption Data Source - decort"
subcategory: ""
description: |-
---
# decort_sep_consumption (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `sep_id` (Number) sep id
### Optional
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `by_pool` (List of Object) consumption divided by pool (see [below for nested schema](#nestedatt--by_pool))
- `id` (String) The ID of this resource.
- `total` (List of Object) total consumption (see [below for nested schema](#nestedatt--total))
- `type` (String) sep type
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)
<a id="nestedatt--by_pool"></a>
### Nested Schema for `by_pool`
Read-Only:
- `disk_count` (Number)
- `disk_usage` (Number)
- `name` (String)
- `snapshot_count` (Number)
- `snapshot_usage` (Number)
- `usage` (Number)
- `usage_limit` (Number)
<a id="nestedatt--total"></a>
### Nested Schema for `total`
Read-Only:
- `capacity_limit` (Number)
- `disk_count` (Number)
- `disk_usage` (Number)
- `snapshot_count` (Number)
- `snapshot_usage` (Number)
- `usage` (Number)
- `usage_limit` (Number)

View File

@@ -1,40 +0,0 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "decort_sep_disk_list Data Source - decort"
subcategory: ""
description: |-
---
# decort_sep_disk_list (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `sep_id` (Number) storage endpoint provider ID
### Optional
- `pool_name` (String) pool name
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
### Read-Only
- `id` (String) The ID of this resource.
- `items` (List of Number) sep disk list
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Optional:
- `default` (String)
- `read` (String)

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